diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index e2bdd7b94fd9..c4a955d25451 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -10,12 +10,16 @@ config SUPERH
 	select EMBEDDED
 	select HAVE_CLK
 	select HAVE_IDE
+	select HAVE_LMB
 	select HAVE_OPROFILE
 	select HAVE_GENERIC_DMA_COHERENT
 	select HAVE_IOREMAP_PROT if MMU
 	select HAVE_ARCH_TRACEHOOK
 	select HAVE_DMA_API_DEBUG
 	select HAVE_PERF_COUNTERS
+	select HAVE_KERNEL_GZIP
+	select HAVE_KERNEL_BZIP2
+	select HAVE_KERNEL_LZMA
 	select RTC_LIB
 	select GENERIC_ATOMIC64
 	help
@@ -31,6 +35,9 @@ config SUPERH32
 	select HAVE_FUNCTION_TRACER
 	select HAVE_FTRACE_MCOUNT_RECORD
 	select HAVE_DYNAMIC_FTRACE
+	select HAVE_FUNCTION_TRACE_MCOUNT_TEST
+	select HAVE_FTRACE_SYSCALLS
+	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_ARCH_KGDB
 	select ARCH_HIBERNATION_POSSIBLE if MMU
 
diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug
index 39224b57c6ef..741d20fab2e1 100644
--- a/arch/sh/Kconfig.debug
+++ b/arch/sh/Kconfig.debug
@@ -38,11 +38,12 @@ config EARLY_SCIF_CONSOLE_PORT
 	default "0xffe00000" if CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7763 || \
 				CPU_SUBTYPE_SH7722 || CPU_SUBTYPE_SH7366 || \
 				CPU_SUBTYPE_SH7343
-	default "0xffea0000" if CPU_SUBTYPE_SH7785
+	default "0xffeb0000" if CPU_SUBTYPE_SH7785
 	default "0xffeb0000" if CPU_SUBTYPE_SH7786
 	default "0xfffe8000" if CPU_SUBTYPE_SH7203
 	default "0xfffe9800" if CPU_SUBTYPE_SH7206 || CPU_SUBTYPE_SH7263
 	default "0xffe80000" if CPU_SH4
+	default "0xa4000150" if CPU_SH3
 	default "0x00000000"
 
 config EARLY_PRINTK
@@ -61,12 +62,14 @@ config EARLY_PRINTK
 	  select both the EARLY_SCIF_CONSOLE and SH_STANDARD_BIOS, using
 	  the kernel command line option to toggle back and forth.
 
-config DEBUG_STACKOVERFLOW
+config STACK_DEBUG
 	bool "Check for stack overflows"
 	depends on DEBUG_KERNEL && SUPERH32
 	help
 	  This option will cause messages to be printed if free stack space
-	  drops below a certain limit.
+	  drops below a certain limit. Saying Y here will add overhead to
+	  every function call and will therefore incur a major
+	  performance hit. Most users should say N.
 
 config DEBUG_STACK_USAGE
 	bool "Stack utilization instrumentation"
@@ -107,6 +110,14 @@ config DUMP_CODE
 
 	  Those looking for more verbose debugging output should say Y.
 
+config DWARF_UNWINDER
+	bool "Enable the DWARF unwinder for stacktraces"
+	select FRAME_POINTER
+	default n
+	help
+	  Enabling this option will make stacktraces more accurate, at
+	  the cost of an increase in overall kernel size.
+
 config SH_NO_BSS_INIT
 	bool "Avoid zeroing BSS (to speed-up startup on suitable platforms)"
 	depends on DEBUG_KERNEL
@@ -123,4 +134,9 @@ config SH64_SR_WATCH
 	bool "Debug: set SR.WATCH to enable hardware watchpoints and trace"
 	depends on SUPERH64
 
+config MCOUNT
+	def_bool y
+	depends on SUPERH32
+	depends on STACK_DEBUG || FUNCTION_TRACER
+
 endmenu
diff --git a/arch/sh/Makefile b/arch/sh/Makefile
index 75d049b03f7e..e26421bf9976 100644
--- a/arch/sh/Makefile
+++ b/arch/sh/Makefile
@@ -136,6 +136,7 @@ machdir-$(CONFIG_SH_7751_SYSTEMH)		+= mach-systemh
 machdir-$(CONFIG_SH_EDOSK7705)			+= mach-edosk7705
 machdir-$(CONFIG_SH_HIGHLANDER)			+= mach-highlander
 machdir-$(CONFIG_SH_MIGOR)			+= mach-migor
+machdir-$(CONFIG_SH_KFR2R09)			+= mach-kfr2r09
 machdir-$(CONFIG_SH_SDK7780)			+= mach-sdk7780
 machdir-$(CONFIG_SH_X3PROTO)			+= mach-x3proto
 machdir-$(CONFIG_SH_SH7763RDP)			+= mach-sh7763rdp
@@ -186,17 +187,27 @@ KBUILD_CFLAGS		+= -pipe $(cflags-y)
 KBUILD_CPPFLAGS		+= $(cflags-y)
 KBUILD_AFLAGS		+= $(cflags-y)
 
+ifeq ($(CONFIG_MCOUNT),y)
+  KBUILD_CFLAGS += -pg
+endif
+
+ifeq ($(CONFIG_DWARF_UNWINDER),y)
+  KBUILD_CFLAGS += -fasynchronous-unwind-tables
+endif
+
 libs-$(CONFIG_SUPERH32)		:= arch/sh/lib/	$(libs-y)
 libs-$(CONFIG_SUPERH64)		:= arch/sh/lib64/ $(libs-y)
 
-PHONY += maketools FORCE
+BOOT_TARGETS = uImage uImage.bz2 uImage.gz uImage.lzma uImage.srec \
+	       zImage vmlinux.srec romImage
+PHONY += maketools $(BOOT_TARGETS) FORCE
 
 maketools:  include/linux/version.h FORCE
 	$(Q)$(MAKE) $(build)=arch/sh/tools include/asm-sh/machtypes.h
 
 all: $(KBUILD_IMAGE)
 
-zImage uImage uImage.srec vmlinux.srec: vmlinux
+$(BOOT_TARGETS): vmlinux
 	$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
 
 compressed: zImage
@@ -208,10 +219,14 @@ archclean:
 	$(Q)$(MAKE) $(clean)=arch/sh/kernel/vsyscall
 
 define archhelp
-	@echo '* zImage 	           - Compressed kernel image'
+	@echo '  zImage 	           - Compressed kernel image'
+	@echo '  romImage	           - Compressed ROM image, if supported'
 	@echo '  vmlinux.srec	           - Create an ELF S-record'
-	@echo '  uImage  	           - Create a bootable image for U-Boot'
-	@echo '  uImage.srec  	           - Create an S-record for U-Boot'
+	@echo '* uImage  	           - Alias to bootable U-Boot image'
+	@echo '  uImage.srec	           - Create an S-record for U-Boot'
+	@echo '* uImage.gz	           - Kernel-only image for U-Boot (gzip)'
+	@echo '  uImage.bz2	           - Kernel-only image for U-Boot (bzip2)'
+	@echo '  uImage.lzma	           - Kernel-only image for U-Boot (lzma)'
 endef
 
 CLEAN_FILES += include/asm-sh/machtypes.h
diff --git a/arch/sh/boards/Kconfig b/arch/sh/boards/Kconfig
index 2b1af0eefa6a..db04c85971ad 100644
--- a/arch/sh/boards/Kconfig
+++ b/arch/sh/boards/Kconfig
@@ -193,6 +193,13 @@ config SH_AP325RXA
 	  Renesas "AP-325RXA" support.
 	  Compatible with ALGO SYSTEM CO.,LTD. "AP-320A"
 
+config SH_KFR2R09
+	bool "KFR2R09"
+	depends on CPU_SUBTYPE_SH7724
+	select ARCH_REQUIRE_GPIOLIB
+	help
+	  "Kit For R2R for 2009" support.
+
 config SH_SH7763RDP
 	bool "SH7763RDP"
 	depends on CPU_SUBTYPE_SH7763
diff --git a/arch/sh/boards/board-ap325rxa.c b/arch/sh/boards/board-ap325rxa.c
index b9c88cc519e2..19eea4ab1ccc 100644
--- a/arch/sh/boards/board-ap325rxa.c
+++ b/arch/sh/boards/board-ap325rxa.c
@@ -227,6 +227,9 @@ static struct platform_device lcdc_device = {
 	.dev		= {
 		.platform_data	= &lcdc_info,
 	},
+	.archdata = {
+		.hwblk_id = HWBLK_LCDC,
+	},
 };
 
 static void camera_power(int val)
@@ -377,6 +380,9 @@ static struct platform_device ceu_device = {
 	.dev		= {
 		.platform_data	= &sh_mobile_ceu_info,
 	},
+	.archdata = {
+		.hwblk_id = HWBLK_CEU,
+	},
 };
 
 struct spi_gpio_platform_data sdcard_cn3_platform_data = {
diff --git a/arch/sh/boards/mach-highlander/setup.c b/arch/sh/boards/mach-highlander/setup.c
index 1639f8915000..566e69d8d729 100644
--- a/arch/sh/boards/mach-highlander/setup.c
+++ b/arch/sh/boards/mach-highlander/setup.c
@@ -22,6 +22,7 @@
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/usb/r8a66597.h>
+#include <linux/usb/m66592.h>
 #include <net/ax88796.h>
 #include <asm/machvec.h>
 #include <mach/highlander.h>
@@ -60,6 +61,11 @@ static struct platform_device r8a66597_usb_host_device = {
 	.resource	= r8a66597_usb_host_resources,
 };
 
+static struct m66592_platdata usbf_platdata = {
+	.xtal = M66592_PLATDATA_XTAL_24MHZ,
+	.vif = 1,
+};
+
 static struct resource m66592_usb_peripheral_resources[] = {
 	[0] = {
 		.name	= "m66592_udc",
@@ -81,6 +87,7 @@ static struct platform_device m66592_usb_peripheral_device = {
 	.dev = {
 		.dma_mask		= NULL,		/* don't use dma */
 		.coherent_dma_mask	= 0xffffffff,
+		.platform_data		= &usbf_platdata,
 	},
 	.num_resources	= ARRAY_SIZE(m66592_usb_peripheral_resources),
 	.resource	= m66592_usb_peripheral_resources,
diff --git a/arch/sh/boards/mach-kfr2r09/Makefile b/arch/sh/boards/mach-kfr2r09/Makefile
new file mode 100644
index 000000000000..5d5867826e3b
--- /dev/null
+++ b/arch/sh/boards/mach-kfr2r09/Makefile
@@ -0,0 +1,2 @@
+obj-y	 := setup.o
+obj-$(CONFIG_FB_SH_MOBILE_LCDC)	+=  lcd_wqvga.o
diff --git a/arch/sh/boards/mach-kfr2r09/lcd_wqvga.c b/arch/sh/boards/mach-kfr2r09/lcd_wqvga.c
new file mode 100644
index 000000000000..8ccb1cc8b589
--- /dev/null
+++ b/arch/sh/boards/mach-kfr2r09/lcd_wqvga.c
@@ -0,0 +1,332 @@
+/*
+ * KFR2R09 LCD panel support
+ *
+ * Copyright (C) 2009 Magnus Damm
+ *
+ * Register settings based on the out-of-tree t33fb.c driver
+ * Copyright (C) 2008 Lineo Solutions, Inc.
+ *
+ * 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/delay.h>
+#include <linux/err.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <video/sh_mobile_lcdc.h>
+#include <mach/kfr2r09.h>
+#include <cpu/sh7724.h>
+
+/* The on-board LCD module is a Hitachi TX07D34VM0AAA. This module is made
+ * up of a 240x400 LCD hooked up to a R61517 driver IC. The driver IC is
+ * communicating with the main port of the LCDC using an 18-bit SYS interface.
+ *
+ * The device code for this LCD module is 0x01221517.
+ */
+
+static const unsigned char data_frame_if[] = {
+	0x02, /* WEMODE: 1=cont, 0=one-shot */
+	0x00, 0x00,
+	0x00, /* EPF, DFM */
+	0x02, /* RIM[1] : 1 (18bpp) */
+};
+
+static const unsigned char data_panel[] = {
+	0x0b,
+	0x63, /* 400 lines */
+	0x04, 0x00, 0x00, 0x04, 0x11, 0x00, 0x00,
+};
+
+static const unsigned char data_timing[] = {
+	0x00, 0x00, 0x13, 0x08, 0x08,
+};
+
+static const unsigned char data_timing_src[] = {
+	0x11, 0x01, 0x00, 0x01,
+};
+
+static const unsigned char data_gamma[] = {
+	0x01, 0x02, 0x08, 0x23,	0x03, 0x0c, 0x00, 0x06,	0x00, 0x00,
+	0x01, 0x00, 0x0c, 0x23, 0x03, 0x08, 0x02, 0x06, 0x00, 0x00,
+};
+
+static const unsigned char data_power[] = {
+	0x07, 0xc5, 0xdc, 0x02,	0x33, 0x0a,
+};
+
+static unsigned long read_reg(void *sohandle,
+			      struct sh_mobile_lcdc_sys_bus_ops *so)
+{
+	return so->read_data(sohandle);
+}
+
+static void write_reg(void *sohandle,
+		      struct sh_mobile_lcdc_sys_bus_ops *so,
+		      int i, unsigned long v)
+{
+	if (i)
+		so->write_data(sohandle, v); /* PTH4/LCDRS High [param, 17:0] */
+	else
+		so->write_index(sohandle, v); /* PTH4/LCDRS Low [cmd, 7:0] */
+}
+
+static void write_data(void *sohandle,
+		       struct sh_mobile_lcdc_sys_bus_ops *so,
+		       unsigned char const *data, int no_data)
+{
+	int i;
+
+	for (i = 0; i < no_data; i++)
+		write_reg(sohandle, so, 1, data[i]);
+}
+
+static unsigned long read_device_code(void *sohandle,
+				      struct sh_mobile_lcdc_sys_bus_ops *so)
+{
+	unsigned long device_code;
+
+	/* access protect OFF */
+	write_reg(sohandle, so, 0, 0xb0);
+	write_reg(sohandle, so, 1, 0x00);
+
+	/* deep standby OFF */
+	write_reg(sohandle, so, 0, 0xb1);
+	write_reg(sohandle, so, 1, 0x00);
+
+	/* device code command */
+	write_reg(sohandle, so, 0, 0xbf);
+	mdelay(50);
+
+	/* dummy read */
+	read_reg(sohandle, so);
+
+	/* read device code */
+	device_code = ((read_reg(sohandle, so) & 0xff) << 24);
+	device_code |= ((read_reg(sohandle, so) & 0xff) << 16);
+	device_code |= ((read_reg(sohandle, so) & 0xff) << 8);
+	device_code |= (read_reg(sohandle, so) & 0xff);
+
+	return device_code;
+}
+
+static void write_memory_start(void *sohandle,
+			       struct sh_mobile_lcdc_sys_bus_ops *so)
+{
+	write_reg(sohandle, so, 0, 0x2c);
+}
+
+static void clear_memory(void *sohandle,
+			 struct sh_mobile_lcdc_sys_bus_ops *so)
+{
+	int i;
+
+	/* write start */
+	write_memory_start(sohandle, so);
+
+	/* paint it black */
+	for (i = 0; i < (240 * 400); i++)
+		write_reg(sohandle, so, 1, 0x00);
+}
+
+static void display_on(void *sohandle,
+		       struct sh_mobile_lcdc_sys_bus_ops *so)
+{
+	/* access protect off */
+	write_reg(sohandle, so, 0, 0xb0);
+	write_reg(sohandle, so, 1, 0x00);
+
+	/* exit deep standby mode */
+	write_reg(sohandle, so, 0, 0xb1);
+	write_reg(sohandle, so, 1, 0x00);
+
+	/* frame memory I/F */
+	write_reg(sohandle, so, 0, 0xb3);
+	write_data(sohandle, so, data_frame_if, ARRAY_SIZE(data_frame_if));
+
+	/* display mode and frame memory write mode */
+	write_reg(sohandle, so, 0, 0xb4);
+	write_reg(sohandle, so, 1, 0x00); /* DBI, internal clock */
+
+	/* panel */
+	write_reg(sohandle, so, 0, 0xc0);
+	write_data(sohandle, so, data_panel, ARRAY_SIZE(data_panel));
+
+	/* timing (normal) */
+	write_reg(sohandle, so, 0, 0xc1);
+	write_data(sohandle, so, data_timing, ARRAY_SIZE(data_timing));
+
+	/* timing (partial) */
+	write_reg(sohandle, so, 0, 0xc2);
+	write_data(sohandle, so, data_timing, ARRAY_SIZE(data_timing));
+
+	/* timing (idle) */
+	write_reg(sohandle, so, 0, 0xc3);
+	write_data(sohandle, so, data_timing, ARRAY_SIZE(data_timing));
+
+	/* timing (source/VCOM/gate driving) */
+	write_reg(sohandle, so, 0, 0xc4);
+	write_data(sohandle, so, data_timing_src, ARRAY_SIZE(data_timing_src));
+
+	/* gamma (red) */
+	write_reg(sohandle, so, 0, 0xc8);
+	write_data(sohandle, so, data_gamma, ARRAY_SIZE(data_gamma));
+
+	/* gamma (green) */
+	write_reg(sohandle, so, 0, 0xc9);
+	write_data(sohandle, so, data_gamma, ARRAY_SIZE(data_gamma));
+
+	/* gamma (blue) */
+	write_reg(sohandle, so, 0, 0xca);
+	write_data(sohandle, so, data_gamma, ARRAY_SIZE(data_gamma));
+
+	/* power (common) */
+	write_reg(sohandle, so, 0, 0xd0);
+	write_data(sohandle, so, data_power, ARRAY_SIZE(data_power));
+
+	/* VCOM */
+	write_reg(sohandle, so, 0, 0xd1);
+	write_reg(sohandle, so, 1, 0x00);
+	write_reg(sohandle, so, 1, 0x0f);
+	write_reg(sohandle, so, 1, 0x02);
+
+	/* power (normal) */
+	write_reg(sohandle, so, 0, 0xd2);
+	write_reg(sohandle, so, 1, 0x63);
+	write_reg(sohandle, so, 1, 0x24);
+
+	/* power (partial) */
+	write_reg(sohandle, so, 0, 0xd3);
+	write_reg(sohandle, so, 1, 0x63);
+	write_reg(sohandle, so, 1, 0x24);
+
+	/* power (idle) */
+	write_reg(sohandle, so, 0, 0xd4);
+	write_reg(sohandle, so, 1, 0x63);
+	write_reg(sohandle, so, 1, 0x24);
+
+	write_reg(sohandle, so, 0, 0xd8);
+	write_reg(sohandle, so, 1, 0x77);
+	write_reg(sohandle, so, 1, 0x77);
+
+	/* TE signal */
+	write_reg(sohandle, so, 0, 0x35);
+	write_reg(sohandle, so, 1, 0x00);
+
+	/* TE signal line */
+	write_reg(sohandle, so, 0, 0x44);
+	write_reg(sohandle, so, 1, 0x00);
+	write_reg(sohandle, so, 1, 0x00);
+
+	/* column address */
+	write_reg(sohandle, so, 0, 0x2a);
+	write_reg(sohandle, so, 1, 0x00);
+	write_reg(sohandle, so, 1, 0x00);
+	write_reg(sohandle, so, 1, 0x00);
+	write_reg(sohandle, so, 1, 0xef);
+
+	/* page address */
+	write_reg(sohandle, so, 0, 0x2b);
+	write_reg(sohandle, so, 1, 0x00);
+	write_reg(sohandle, so, 1, 0x00);
+	write_reg(sohandle, so, 1, 0x01);
+	write_reg(sohandle, so, 1, 0x8f);
+
+	/* exit sleep mode */
+	write_reg(sohandle, so, 0, 0x11);
+
+	mdelay(120);
+
+	/* clear vram */
+	clear_memory(sohandle, so);
+
+	/* display ON */
+	write_reg(sohandle, so, 0, 0x29);
+	mdelay(1);
+
+	write_memory_start(sohandle, so);
+}
+
+int kfr2r09_lcd_setup(void *board_data, void *sohandle,
+		      struct sh_mobile_lcdc_sys_bus_ops *so)
+{
+	/* power on */
+	gpio_set_value(GPIO_PTF4, 0);  /* PROTECT/ -> L */
+	gpio_set_value(GPIO_PTE4, 0);  /* LCD_RST/ -> L */
+	gpio_set_value(GPIO_PTF4, 1);  /* PROTECT/ -> H */
+	udelay(1100);
+	gpio_set_value(GPIO_PTE4, 1);  /* LCD_RST/ -> H */
+	udelay(10);
+	gpio_set_value(GPIO_PTF4, 0);  /* PROTECT/ -> L */
+	mdelay(20);
+
+	if (read_device_code(sohandle, so) != 0x01221517)
+		return -ENODEV;
+
+	pr_info("KFR2R09 WQVGA LCD Module detected.\n");
+
+	display_on(sohandle, so);
+	return 0;
+}
+
+#define CTRL_CKSW       0x10
+#define CTRL_C10        0x20
+#define CTRL_CPSW       0x80
+#define MAIN_MLED4      0x40
+#define MAIN_MSW        0x80
+
+static int kfr2r09_lcd_backlight(int on)
+{
+	struct i2c_adapter *a;
+	struct i2c_msg msg;
+	unsigned char buf[2];
+	int ret;
+
+	a = i2c_get_adapter(0);
+	if (!a)
+		return -ENODEV;
+
+	buf[0] = 0x00;
+	if (on)
+		buf[1] = CTRL_CPSW | CTRL_C10 | CTRL_CKSW;
+	else
+		buf[1] = 0;
+
+	msg.addr = 0x75;
+	msg.buf = buf;
+	msg.len = 2;
+	msg.flags = 0;
+	ret = i2c_transfer(a, &msg, 1);
+	if (ret != 1)
+		return -ENODEV;
+
+	buf[0] = 0x01;
+	if (on)
+		buf[1] = MAIN_MSW | MAIN_MLED4 | 0x0c;
+	else
+		buf[1] = 0;
+
+	msg.addr = 0x75;
+	msg.buf = buf;
+	msg.len = 2;
+	msg.flags = 0;
+	ret = i2c_transfer(a, &msg, 1);
+	if (ret != 1)
+		return -ENODEV;
+
+	return 0;
+}
+
+void kfr2r09_lcd_on(void *board_data)
+{
+	kfr2r09_lcd_backlight(1);
+}
+
+void kfr2r09_lcd_off(void *board_data)
+{
+	kfr2r09_lcd_backlight(0);
+}
diff --git a/arch/sh/boards/mach-kfr2r09/setup.c b/arch/sh/boards/mach-kfr2r09/setup.c
new file mode 100644
index 000000000000..f9ba43635dc1
--- /dev/null
+++ b/arch/sh/boards/mach-kfr2r09/setup.c
@@ -0,0 +1,276 @@
+/*
+ * KFR2R09 board support code
+ *
+ * Copyright (C) 2009 Magnus Damm
+ *
+ * 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/init.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/mtd/physmap.h>
+#include <linux/mtd/onenand.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/gpio.h>
+#include <linux/input.h>
+#include <video/sh_mobile_lcdc.h>
+#include <asm/clock.h>
+#include <asm/machvec.h>
+#include <asm/io.h>
+#include <asm/sh_keysc.h>
+#include <cpu/sh7724.h>
+#include <mach/kfr2r09.h>
+
+static struct mtd_partition kfr2r09_nor_flash_partitions[] =
+{
+	{
+		.name = "boot",
+		.offset = 0,
+		.size = (4 * 1024 * 1024),
+		.mask_flags = MTD_WRITEABLE,	/* Read-only */
+	},
+	{
+		.name = "other",
+		.offset = MTDPART_OFS_APPEND,
+		.size = MTDPART_SIZ_FULL,
+	},
+};
+
+static struct physmap_flash_data kfr2r09_nor_flash_data = {
+	.width		= 2,
+	.parts		= kfr2r09_nor_flash_partitions,
+	.nr_parts	= ARRAY_SIZE(kfr2r09_nor_flash_partitions),
+};
+
+static struct resource kfr2r09_nor_flash_resources[] = {
+	[0] = {
+		.name		= "NOR Flash",
+		.start		= 0x00000000,
+		.end		= 0x03ffffff,
+		.flags		= IORESOURCE_MEM,
+	}
+};
+
+static struct platform_device kfr2r09_nor_flash_device = {
+	.name		= "physmap-flash",
+	.resource	= kfr2r09_nor_flash_resources,
+	.num_resources	= ARRAY_SIZE(kfr2r09_nor_flash_resources),
+	.dev		= {
+		.platform_data = &kfr2r09_nor_flash_data,
+	},
+};
+
+static struct resource kfr2r09_nand_flash_resources[] = {
+	[0] = {
+		.name		= "NAND Flash",
+		.start		= 0x10000000,
+		.end		= 0x1001ffff,
+		.flags		= IORESOURCE_MEM,
+	}
+};
+
+static struct platform_device kfr2r09_nand_flash_device = {
+	.name		= "onenand-flash",
+	.resource	= kfr2r09_nand_flash_resources,
+	.num_resources	= ARRAY_SIZE(kfr2r09_nand_flash_resources),
+};
+
+static struct sh_keysc_info kfr2r09_sh_keysc_info = {
+	.mode = SH_KEYSC_MODE_1, /* KEYOUT0->4, KEYIN0->4 */
+	.scan_timing = 3,
+	.delay = 10,
+	.keycodes = {
+		KEY_PHONE, KEY_CLEAR, KEY_MAIL, KEY_WWW, KEY_ENTER,
+		KEY_1, KEY_2, KEY_3, 0, KEY_UP,
+		KEY_4, KEY_5, KEY_6, 0, KEY_LEFT,
+		KEY_7, KEY_8, KEY_9, KEY_PROG1, KEY_RIGHT,
+		KEY_S, KEY_0, KEY_P, KEY_PROG2, KEY_DOWN,
+		0, 0, 0, 0, 0
+	},
+};
+
+static struct resource kfr2r09_sh_keysc_resources[] = {
+	[0] = {
+		.name	= "KEYSC",
+		.start  = 0x044b0000,
+		.end    = 0x044b000f,
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = 79,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device kfr2r09_sh_keysc_device = {
+	.name           = "sh_keysc",
+	.id             = 0, /* "keysc0" clock */
+	.num_resources  = ARRAY_SIZE(kfr2r09_sh_keysc_resources),
+	.resource       = kfr2r09_sh_keysc_resources,
+	.dev	= {
+		.platform_data	= &kfr2r09_sh_keysc_info,
+	},
+	.archdata = {
+		.hwblk_id = HWBLK_KEYSC,
+	},
+};
+
+static struct sh_mobile_lcdc_info kfr2r09_sh_lcdc_info = {
+	.clock_source = LCDC_CLK_BUS,
+	.ch[0] = {
+		.chan = LCDC_CHAN_MAINLCD,
+		.bpp = 16,
+		.interface_type = SYS18,
+		.clock_divider = 6,
+		.flags = LCDC_FLAGS_DWPOL,
+		.lcd_cfg = {
+			.name = "TX07D34VM0AAA",
+			.xres = 240,
+			.yres = 400,
+			.left_margin = 0,
+			.right_margin = 16,
+			.hsync_len = 8,
+			.upper_margin = 0,
+			.lower_margin = 1,
+			.vsync_len = 1,
+			.sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		},
+		.lcd_size_cfg = {
+			.width = 35,
+			.height = 58,
+		},
+		.board_cfg = {
+			.setup_sys = kfr2r09_lcd_setup,
+			.display_on = kfr2r09_lcd_on,
+			.display_off = kfr2r09_lcd_off,
+		},
+		.sys_bus_cfg = {
+			.ldmt2r = 0x07010904,
+			.ldmt3r = 0x14012914,
+			/* set 1s delay to encourage fsync() */
+			.deferred_io_msec = 1000,
+		},
+	}
+};
+
+static struct resource kfr2r09_sh_lcdc_resources[] = {
+	[0] = {
+		.name	= "LCDC",
+		.start	= 0xfe940000, /* P4-only space */
+		.end	= 0xfe941fff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 106,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device kfr2r09_sh_lcdc_device = {
+	.name		= "sh_mobile_lcdc_fb",
+	.num_resources	= ARRAY_SIZE(kfr2r09_sh_lcdc_resources),
+	.resource	= kfr2r09_sh_lcdc_resources,
+	.dev	= {
+		.platform_data	= &kfr2r09_sh_lcdc_info,
+	},
+	.archdata = {
+		.hwblk_id = HWBLK_LCDC,
+	},
+};
+
+static struct platform_device *kfr2r09_devices[] __initdata = {
+	&kfr2r09_nor_flash_device,
+	&kfr2r09_nand_flash_device,
+	&kfr2r09_sh_keysc_device,
+	&kfr2r09_sh_lcdc_device,
+};
+
+#define BSC_CS0BCR 0xfec10004
+#define BSC_CS0WCR 0xfec10024
+#define BSC_CS4BCR 0xfec10010
+#define BSC_CS4WCR 0xfec10030
+
+static int __init kfr2r09_devices_setup(void)
+{
+	/* enable SCIF1 serial port for YC401 console support */
+	gpio_request(GPIO_FN_SCIF1_RXD, NULL);
+	gpio_request(GPIO_FN_SCIF1_TXD, NULL);
+
+	/* setup NOR flash at CS0 */
+	ctrl_outl(0x36db0400, BSC_CS0BCR);
+	ctrl_outl(0x00000500, BSC_CS0WCR);
+
+	/* setup NAND flash at CS4 */
+	ctrl_outl(0x36db0400, BSC_CS4BCR);
+	ctrl_outl(0x00000500, BSC_CS4WCR);
+
+	/* setup KEYSC pins */
+	gpio_request(GPIO_FN_KEYOUT0, NULL);
+	gpio_request(GPIO_FN_KEYOUT1, NULL);
+	gpio_request(GPIO_FN_KEYOUT2, NULL);
+	gpio_request(GPIO_FN_KEYOUT3, NULL);
+	gpio_request(GPIO_FN_KEYOUT4_IN6, NULL);
+	gpio_request(GPIO_FN_KEYIN0, NULL);
+	gpio_request(GPIO_FN_KEYIN1, NULL);
+	gpio_request(GPIO_FN_KEYIN2, NULL);
+	gpio_request(GPIO_FN_KEYIN3, NULL);
+	gpio_request(GPIO_FN_KEYIN4, NULL);
+	gpio_request(GPIO_FN_KEYOUT5_IN5, NULL);
+
+	/* setup LCDC pins for SYS panel */
+	gpio_request(GPIO_FN_LCDD17, NULL);
+	gpio_request(GPIO_FN_LCDD16, NULL);
+	gpio_request(GPIO_FN_LCDD15, NULL);
+	gpio_request(GPIO_FN_LCDD14, NULL);
+	gpio_request(GPIO_FN_LCDD13, NULL);
+	gpio_request(GPIO_FN_LCDD12, NULL);
+	gpio_request(GPIO_FN_LCDD11, NULL);
+	gpio_request(GPIO_FN_LCDD10, NULL);
+	gpio_request(GPIO_FN_LCDD9, NULL);
+	gpio_request(GPIO_FN_LCDD8, NULL);
+	gpio_request(GPIO_FN_LCDD7, NULL);
+	gpio_request(GPIO_FN_LCDD6, NULL);
+	gpio_request(GPIO_FN_LCDD5, NULL);
+	gpio_request(GPIO_FN_LCDD4, NULL);
+	gpio_request(GPIO_FN_LCDD3, NULL);
+	gpio_request(GPIO_FN_LCDD2, NULL);
+	gpio_request(GPIO_FN_LCDD1, NULL);
+	gpio_request(GPIO_FN_LCDD0, NULL);
+	gpio_request(GPIO_FN_LCDRS, NULL); /* LCD_RS */
+	gpio_request(GPIO_FN_LCDCS, NULL); /* LCD_CS/ */
+	gpio_request(GPIO_FN_LCDRD, NULL); /* LCD_RD/ */
+	gpio_request(GPIO_FN_LCDWR, NULL); /* LCD_WR/ */
+	gpio_request(GPIO_FN_LCDVSYN, NULL); /* LCD_VSYNC */
+	gpio_request(GPIO_PTE4, NULL); /* LCD_RST/ */
+	gpio_direction_output(GPIO_PTE4, 1);
+	gpio_request(GPIO_PTF4, NULL); /* PROTECT/ */
+	gpio_direction_output(GPIO_PTF4, 1);
+	gpio_request(GPIO_PTU0, NULL); /* LEDSTDBY/ */
+	gpio_direction_output(GPIO_PTU0, 1);
+
+	return platform_add_devices(kfr2r09_devices,
+				    ARRAY_SIZE(kfr2r09_devices));
+}
+device_initcall(kfr2r09_devices_setup);
+
+/* Return the board specific boot mode pin configuration */
+static int kfr2r09_mode_pins(void)
+{
+	/* MD0=1, MD1=1, MD2=0: Clock Mode 3
+	 * MD3=0: 16-bit Area0 Bus Width
+	 * MD5=1: Little Endian
+	 * MD8=1: Test Mode Disabled
+	 */
+	return MODE_PIN0 | MODE_PIN1 | MODE_PIN5 | MODE_PIN8;
+}
+
+/*
+ * The Machine Vector
+ */
+static struct sh_machine_vector mv_kfr2r09 __initmv = {
+	.mv_name		= "kfr2r09",
+	.mv_mode_pins		= kfr2r09_mode_pins,
+};
diff --git a/arch/sh/boards/mach-migor/setup.c b/arch/sh/boards/mach-migor/setup.c
index f9b2e4df35b9..be8f0d94f6f1 100644
--- a/arch/sh/boards/mach-migor/setup.c
+++ b/arch/sh/boards/mach-migor/setup.c
@@ -98,6 +98,9 @@ static struct platform_device sh_keysc_device = {
 	.dev	= {
 		.platform_data	= &sh_keysc_info,
 	},
+	.archdata = {
+		.hwblk_id = HWBLK_KEYSC,
+	},
 };
 
 static struct mtd_partition migor_nor_flash_partitions[] =
@@ -292,6 +295,9 @@ static struct platform_device migor_lcdc_device = {
 	.dev	= {
 		.platform_data	= &sh_mobile_lcdc_info,
 	},
+	.archdata = {
+		.hwblk_id = HWBLK_LCDC,
+	},
 };
 
 static struct clk *camera_clk;
@@ -379,6 +385,9 @@ static struct platform_device migor_ceu_device = {
 	.dev	= {
 		.platform_data	= &sh_mobile_ceu_info,
 	},
+	.archdata = {
+		.hwblk_id = HWBLK_CEU,
+	},
 };
 
 struct spi_gpio_platform_data sdcard_cn9_platform_data = {
diff --git a/arch/sh/boards/mach-se/7722/setup.c b/arch/sh/boards/mach-se/7722/setup.c
index af84904ed86f..36374078e521 100644
--- a/arch/sh/boards/mach-se/7722/setup.c
+++ b/arch/sh/boards/mach-se/7722/setup.c
@@ -22,6 +22,7 @@
 #include <asm/io.h>
 #include <asm/heartbeat.h>
 #include <asm/sh_keysc.h>
+#include <cpu/sh7722.h>
 
 /* Heartbeat */
 static struct heartbeat_data heartbeat_data = {
@@ -137,6 +138,9 @@ static struct platform_device sh_keysc_device = {
 	.dev	= {
 		.platform_data	= &sh_keysc_info,
 	},
+	.archdata = {
+		.hwblk_id = HWBLK_KEYSC,
+	},
 };
 
 static struct platform_device *se7722_devices[] __initdata = {
diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c
index 15456a0773bf..d922e1b71410 100644
--- a/arch/sh/boards/mach-se/7724/setup.c
+++ b/arch/sh/boards/mach-se/7724/setup.c
@@ -39,7 +39,15 @@
  * SW41 : abxx xxxx  -> a = 0 : Analog  monitor
  *                          1 : Digital monitor
  *                      b = 0 : VGA
- *                          1 : SVGA
+ *                          1 : 720p
+ */
+
+/*
+ * about 720p
+ *
+ * When you use 1280 x 720 lcdc output,
+ * you should change OSC6 lcdc clock from 25.175MHz to 74.25MHz,
+ * and change SW41 to use 720p
  */
 
 /* Heartbeat */
@@ -174,6 +182,9 @@ static struct platform_device lcdc_device = {
 	.dev		= {
 		.platform_data	= &lcdc_info,
 	},
+	.archdata = {
+		.hwblk_id = HWBLK_LCDC,
+	},
 };
 
 /* CEU0 */
@@ -205,6 +216,9 @@ static struct platform_device ceu0_device = {
 	.dev	= {
 		.platform_data	= &sh_mobile_ceu0_info,
 	},
+	.archdata = {
+		.hwblk_id = HWBLK_CEU0,
+	},
 };
 
 /* CEU1 */
@@ -236,6 +250,9 @@ static struct platform_device ceu1_device = {
 	.dev	= {
 		.platform_data	= &sh_mobile_ceu1_info,
 	},
+	.archdata = {
+		.hwblk_id = HWBLK_CEU1,
+	},
 };
 
 /* KEYSC in SoC (Needs SW33-2 set to ON) */
@@ -274,6 +291,9 @@ static struct platform_device keysc_device = {
 	.dev	= {
 		.platform_data	= &keysc_info,
 	},
+	.archdata = {
+		.hwblk_id = HWBLK_KEYSC,
+	},
 };
 
 /* SH Eth */
@@ -302,9 +322,13 @@ static struct platform_device sh_eth_device = {
 	},
 	.num_resources = ARRAY_SIZE(sh_eth_resources),
 	.resource = sh_eth_resources,
+	.archdata = {
+		.hwblk_id = HWBLK_ETHER,
+	},
 };
 
 static struct r8a66597_platdata sh7724_usb0_host_data = {
+	.on_chip = 1,
 };
 
 static struct resource sh7724_usb0_host_resources[] = {
@@ -330,6 +354,9 @@ static struct platform_device sh7724_usb0_host_device = {
 	},
 	.num_resources	= ARRAY_SIZE(sh7724_usb0_host_resources),
 	.resource	= sh7724_usb0_host_resources,
+	.archdata = {
+		.hwblk_id = HWBLK_USB0,
+	},
 };
 
 static struct platform_device *ms7724se_devices[] __initdata = {
@@ -421,6 +448,32 @@ static int __init devices_setup(void)
 	/* turn on USB clocks, use external clock */
 	ctrl_outw((ctrl_inw(PORT_MSELCRB) & ~0xc000) | 0x8000, PORT_MSELCRB);
 
+#ifdef CONFIG_PM
+	/* Let LED9 show STATUS2 */
+	gpio_request(GPIO_FN_STATUS2, NULL);
+
+	/* Lit LED10 show STATUS0 */
+	gpio_request(GPIO_FN_STATUS0, NULL);
+
+	/* Lit LED11 show PDSTATUS */
+	gpio_request(GPIO_FN_PDSTATUS, NULL);
+#else
+	/* Lit LED9 */
+	gpio_request(GPIO_PTJ6, NULL);
+	gpio_direction_output(GPIO_PTJ6, 1);
+	gpio_export(GPIO_PTJ6, 0);
+
+	/* Lit LED10 */
+	gpio_request(GPIO_PTJ5, NULL);
+	gpio_direction_output(GPIO_PTJ5, 1);
+	gpio_export(GPIO_PTJ5, 0);
+
+	/* Lit LED11 */
+	gpio_request(GPIO_PTJ7, NULL);
+	gpio_direction_output(GPIO_PTJ7, 1);
+	gpio_export(GPIO_PTJ7, 0);
+#endif
+
 	/* enable USB0 port */
 	ctrl_outw(0x0600, 0xa40501d4);
 
@@ -546,15 +599,15 @@ static int __init devices_setup(void)
 	sh_eth_init();
 
 	if (sw & SW41_B) {
-		/* SVGA */
-		lcdc_info.ch[0].lcd_cfg.xres         = 800;
-		lcdc_info.ch[0].lcd_cfg.yres         = 600;
-		lcdc_info.ch[0].lcd_cfg.left_margin  = 142;
-		lcdc_info.ch[0].lcd_cfg.right_margin = 52;
-		lcdc_info.ch[0].lcd_cfg.hsync_len    = 96;
-		lcdc_info.ch[0].lcd_cfg.upper_margin = 24;
-		lcdc_info.ch[0].lcd_cfg.lower_margin = 2;
-		lcdc_info.ch[0].lcd_cfg.vsync_len    = 2;
+		/* 720p */
+		lcdc_info.ch[0].lcd_cfg.xres         = 1280;
+		lcdc_info.ch[0].lcd_cfg.yres         = 720;
+		lcdc_info.ch[0].lcd_cfg.left_margin  = 220;
+		lcdc_info.ch[0].lcd_cfg.right_margin = 110;
+		lcdc_info.ch[0].lcd_cfg.hsync_len    = 40;
+		lcdc_info.ch[0].lcd_cfg.upper_margin = 20;
+		lcdc_info.ch[0].lcd_cfg.lower_margin = 5;
+		lcdc_info.ch[0].lcd_cfg.vsync_len    = 5;
 	} else {
 		/* VGA */
 		lcdc_info.ch[0].lcd_cfg.xres         = 640;
diff --git a/arch/sh/boards/mach-x3proto/setup.c b/arch/sh/boards/mach-x3proto/setup.c
index 8913ae39a802..efe4cb9f8a77 100644
--- a/arch/sh/boards/mach-x3proto/setup.c
+++ b/arch/sh/boards/mach-x3proto/setup.c
@@ -17,6 +17,7 @@
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/usb/r8a66597.h>
+#include <linux/usb/m66592.h>
 #include <asm/ilsel.h>
 
 static struct resource heartbeat_resources[] = {
@@ -89,6 +90,11 @@ static struct platform_device r8a66597_usb_host_device = {
 	.resource	= r8a66597_usb_host_resources,
 };
 
+static struct m66592_platdata usbf_platdata = {
+	.xtal = M66592_PLATDATA_XTAL_24MHZ,
+	.vif = 1,
+};
+
 static struct resource m66592_usb_peripheral_resources[] = {
 	[0] = {
 		.name	= "m66592_udc",
@@ -109,6 +115,7 @@ static struct platform_device m66592_usb_peripheral_device = {
 	.dev = {
 		.dma_mask		= NULL,		/* don't use dma */
 		.coherent_dma_mask	= 0xffffffff,
+		.platform_data		= &usbf_platdata,
 	},
 	.num_resources	= ARRAY_SIZE(m66592_usb_peripheral_resources),
 	.resource	= m66592_usb_peripheral_resources,
diff --git a/arch/sh/boot/.gitignore b/arch/sh/boot/.gitignore
index aad5edddf93b..541087d2029c 100644
--- a/arch/sh/boot/.gitignore
+++ b/arch/sh/boot/.gitignore
@@ -1,4 +1,3 @@
 zImage
-vmlinux.srec
-uImage
-uImage.srec
+vmlinux*
+uImage*
diff --git a/arch/sh/boot/Makefile b/arch/sh/boot/Makefile
index 78efb04c28f3..a1316872be6f 100644
--- a/arch/sh/boot/Makefile
+++ b/arch/sh/boot/Makefile
@@ -20,8 +20,13 @@ CONFIG_BOOT_LINK_OFFSET	?= 0x00800000
 CONFIG_ZERO_PAGE_OFFSET	?= 0x00001000
 CONFIG_ENTRY_OFFSET	?= 0x00001000
 
-targets := zImage vmlinux.srec uImage uImage.srec
-subdir- := compressed
+suffix-$(CONFIG_KERNEL_GZIP)  := gz
+suffix-$(CONFIG_KERNEL_BZIP2) := bz2
+suffix-$(CONFIG_KERNEL_LZMA)  := lzma
+
+targets := zImage vmlinux.srec romImage uImage uImage.srec uImage.gz uImage.bz2 uImage.lzma
+extra-y += vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma
+subdir- := compressed romimage
 
 $(obj)/zImage: $(obj)/compressed/vmlinux FORCE
 	$(call if_changed,objcopy)
@@ -30,6 +35,13 @@ $(obj)/zImage: $(obj)/compressed/vmlinux FORCE
 $(obj)/compressed/vmlinux: FORCE
 	$(Q)$(MAKE) $(build)=$(obj)/compressed $@
 
+$(obj)/romImage: $(obj)/romimage/vmlinux FORCE
+	$(call if_changed,objcopy)
+	@echo '  Kernel: $@ is ready'
+
+$(obj)/romimage/vmlinux: $(obj)/zImage FORCE
+	$(Q)$(MAKE) $(build)=$(obj)/romimage $@
+
 KERNEL_MEMORY := 0x00000000
 ifeq ($(CONFIG_PMB_FIXED),y)
 KERNEL_MEMORY := $(shell /bin/bash -c 'printf "0x%08x" \
@@ -40,9 +52,6 @@ KERNEL_MEMORY := $(shell /bin/bash -c 'printf "0x%08x" \
 		     $$[$(CONFIG_MEMORY_START)]')
 endif
 
-export CONFIG_PAGE_OFFSET CONFIG_MEMORY_START CONFIG_BOOT_LINK_OFFSET \
-       CONFIG_ZERO_PAGE_OFFSET CONFIG_ENTRY_OFFSET KERNEL_MEMORY
-
 KERNEL_LOAD	:= $(shell /bin/bash -c 'printf "0x%08x" \
 		     $$[$(CONFIG_PAGE_OFFSET)  + \
 			$(KERNEL_MEMORY) + \
@@ -55,19 +64,30 @@ KERNEL_ENTRY	:= $(shell /bin/bash -c 'printf "0x%08x" \
 
 quiet_cmd_uimage = UIMAGE  $@
       cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A sh -O linux -T kernel \
-		   -C gzip -a $(KERNEL_LOAD) -e $(KERNEL_ENTRY) \
+		   -C $(2) -a $(KERNEL_LOAD) -e $(KERNEL_ENTRY) \
 		   -n 'Linux-$(KERNELRELEASE)' -d $< $@
 
-$(obj)/uImage: $(obj)/vmlinux.bin.gz FORCE
-	$(call if_changed,uimage)
-	@echo '  Image $@ is ready'
-
 $(obj)/vmlinux.bin: vmlinux FORCE
 	$(call if_changed,objcopy)
 
 $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
 	$(call if_changed,gzip)
 
+$(obj)/vmlinux.bin.bz2: $(obj)/vmlinux.bin FORCE
+	$(call if_changed,bzip2)
+
+$(obj)/vmlinux.bin.lzma: $(obj)/vmlinux.bin FORCE
+	$(call if_changed,lzma)
+
+$(obj)/uImage.bz2: $(obj)/vmlinux.bin.bz2
+	$(call if_changed,uimage,bzip2)
+
+$(obj)/uImage.gz: $(obj)/vmlinux.bin.gz
+	$(call if_changed,uimage,gzip)
+
+$(obj)/uImage.lzma: $(obj)/vmlinux.bin.lzma
+	$(call if_changed,uimage,lzma)
+
 OBJCOPYFLAGS_vmlinux.srec := -I binary -O srec
 $(obj)/vmlinux.srec: $(obj)/compressed/vmlinux
 	$(call if_changed,objcopy)
@@ -76,5 +96,9 @@ OBJCOPYFLAGS_uImage.srec := -I binary -O srec
 $(obj)/uImage.srec: $(obj)/uImage
 	$(call if_changed,objcopy)
 
-clean-files	+= uImage uImage.srec vmlinux.srec \
-		   vmlinux.bin vmlinux.bin.gz
+$(obj)/uImage: $(obj)/uImage.$(suffix-y)
+	@ln -sf $(notdir $<) $@
+	@echo '  Image $@ is ready'
+
+export CONFIG_PAGE_OFFSET CONFIG_MEMORY_START CONFIG_BOOT_LINK_OFFSET \
+       CONFIG_ZERO_PAGE_OFFSET CONFIG_ENTRY_OFFSET KERNEL_MEMORY suffix-y
diff --git a/arch/sh/boot/compressed/.gitignore b/arch/sh/boot/compressed/.gitignore
new file mode 100644
index 000000000000..2374a83d87b2
--- /dev/null
+++ b/arch/sh/boot/compressed/.gitignore
@@ -0,0 +1 @@
+vmlinux.bin.*
diff --git a/arch/sh/boot/compressed/Makefile b/arch/sh/boot/compressed/Makefile
index 9531bf1b7c2f..6182eca5180a 100644
--- a/arch/sh/boot/compressed/Makefile
+++ b/arch/sh/boot/compressed/Makefile
@@ -5,9 +5,10 @@
 #
 
 targets		:= vmlinux vmlinux.bin vmlinux.bin.gz \
-		   head_$(BITS).o misc_$(BITS).o piggy.o
+		   vmlinux.bin.bz2 vmlinux.bin.lzma \
+		   head_$(BITS).o misc.o piggy.o
 
-OBJECTS = $(obj)/head_$(BITS).o $(obj)/misc_$(BITS).o $(obj)/cache.o
+OBJECTS = $(obj)/head_$(BITS).o $(obj)/misc.o $(obj)/cache.o
 
 ifdef CONFIG_SH_STANDARD_BIOS
 OBJECTS += $(obj)/../../kernel/sh_bios.o
@@ -23,7 +24,7 @@ IMAGE_OFFSET	:= $(shell /bin/bash -c 'printf "0x%08x" \
 
 LIBGCC	:= $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
 
-ifeq ($(CONFIG_FUNCTION_TRACER),y)
+ifeq ($(CONFIG_MCOUNT),y)
 ORIG_CFLAGS := $(KBUILD_CFLAGS)
 KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS))
 endif
@@ -38,10 +39,18 @@ $(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o $(LIBGCC) FORCE
 $(obj)/vmlinux.bin: vmlinux FORCE
 	$(call if_changed,objcopy)
 
-$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
+vmlinux.bin.all-y := $(obj)/vmlinux.bin
+
+$(obj)/vmlinux.bin.gz: $(vmlinux.bin.all-y) FORCE
 	$(call if_changed,gzip)
+$(obj)/vmlinux.bin.bz2: $(vmlinux.bin.all-y) FORCE
+	$(call if_changed,bzip2)
+$(obj)/vmlinux.bin.lzma: $(vmlinux.bin.all-y) FORCE
+	$(call if_changed,lzma)
 
 OBJCOPYFLAGS += -R .empty_zero_page
 
-$(obj)/piggy.o: $(obj)/piggy.S $(obj)/vmlinux.bin.gz FORCE
-	$(call if_changed,as_o_S)
+LDFLAGS_piggy.o := -r --format binary --oformat $(ld-bfd) -T
+
+$(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.$(suffix-y) FORCE
+	$(call if_changed,ld)
diff --git a/arch/sh/boot/compressed/misc.c b/arch/sh/boot/compressed/misc.c
new file mode 100644
index 000000000000..fd56a71ca9d9
--- /dev/null
+++ b/arch/sh/boot/compressed/misc.c
@@ -0,0 +1,149 @@
+/*
+ * arch/sh/boot/compressed/misc.c
+ *
+ * This is a collection of several routines from gzip-1.0.3
+ * adapted for Linux.
+ *
+ * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
+ *
+ * Adapted for SH by Stuart Menefy, Aug 1999
+ *
+ * Modified to use standard LinuxSH BIOS by Greg Banks 7Jul2000
+ */
+
+#include <asm/uaccess.h>
+#include <asm/addrspace.h>
+#include <asm/page.h>
+#include <asm/sh_bios.h>
+
+/*
+ * gzip declarations
+ */
+
+#define STATIC static
+
+#undef memset
+#undef memcpy
+#define memzero(s, n)     memset ((s), 0, (n))
+
+/* cache.c */
+#define CACHE_ENABLE      0
+#define CACHE_DISABLE     1
+int cache_control(unsigned int command);
+
+extern char input_data[];
+extern int input_len;
+static unsigned char *output;
+
+static void error(char *m);
+
+int puts(const char *);
+
+extern int _text;		/* Defined in vmlinux.lds.S */
+extern int _end;
+static unsigned long free_mem_ptr;
+static unsigned long free_mem_end_ptr;
+
+#ifdef CONFIG_HAVE_KERNEL_BZIP2
+#define HEAP_SIZE	0x400000
+#else
+#define HEAP_SIZE	0x10000
+#endif
+
+#ifdef CONFIG_KERNEL_GZIP
+#include "../../../../lib/decompress_inflate.c"
+#endif
+
+#ifdef CONFIG_KERNEL_BZIP2
+#include "../../../../lib/decompress_bunzip2.c"
+#endif
+
+#ifdef CONFIG_KERNEL_LZMA
+#include "../../../../lib/decompress_unlzma.c"
+#endif
+
+#ifdef CONFIG_SH_STANDARD_BIOS
+size_t strlen(const char *s)
+{
+	int i = 0;
+
+	while (*s++)
+		i++;
+	return i;
+}
+
+int puts(const char *s)
+{
+	int len = strlen(s);
+	sh_bios_console_write(s, len);
+	return len;
+}
+#else
+int puts(const char *s)
+{
+	/* This should be updated to use the sh-sci routines */
+	return 0;
+}
+#endif
+
+void* memset(void* s, int c, size_t n)
+{
+	int i;
+	char *ss = (char*)s;
+
+	for (i=0;i<n;i++) ss[i] = c;
+	return s;
+}
+
+void* memcpy(void* __dest, __const void* __src,
+			    size_t __n)
+{
+	int i;
+	char *d = (char *)__dest, *s = (char *)__src;
+
+	for (i=0;i<__n;i++) d[i] = s[i];
+	return __dest;
+}
+
+static void error(char *x)
+{
+	puts("\n\n");
+	puts(x);
+	puts("\n\n -- System halted");
+
+	while(1);	/* Halt */
+}
+
+#ifdef CONFIG_SUPERH64
+#define stackalign	8
+#else
+#define stackalign	4
+#endif
+
+#define STACK_SIZE (4096)
+long __attribute__ ((aligned(stackalign))) user_stack[STACK_SIZE];
+long *stack_start = &user_stack[STACK_SIZE];
+
+void decompress_kernel(void)
+{
+	unsigned long output_addr;
+
+#ifdef CONFIG_SUPERH64
+	output_addr = (CONFIG_MEMORY_START + 0x2000);
+#else
+	output_addr = PHYSADDR((unsigned long)&_text+PAGE_SIZE);
+#ifdef CONFIG_29BIT
+	output_addr |= P2SEG;
+#endif
+#endif
+
+	output = (unsigned char *)output_addr;
+	free_mem_ptr = (unsigned long)&_end;
+	free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;
+
+	puts("Uncompressing Linux... ");
+	cache_control(CACHE_ENABLE);
+	decompress(input_data, input_len, NULL, NULL, output, NULL, error);
+	cache_control(CACHE_DISABLE);
+	puts("Ok, booting the kernel.\n");
+}
diff --git a/arch/sh/boot/compressed/misc_32.c b/arch/sh/boot/compressed/misc_32.c
deleted file mode 100644
index efdba6b29572..000000000000
--- a/arch/sh/boot/compressed/misc_32.c
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * arch/sh/boot/compressed/misc.c
- *
- * This is a collection of several routines from gzip-1.0.3
- * adapted for Linux.
- *
- * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
- *
- * Adapted for SH by Stuart Menefy, Aug 1999
- *
- * Modified to use standard LinuxSH BIOS by Greg Banks 7Jul2000
- */
-
-#include <asm/uaccess.h>
-#include <asm/addrspace.h>
-#include <asm/page.h>
-#ifdef CONFIG_SH_STANDARD_BIOS
-#include <asm/sh_bios.h>
-#endif
-
-/*
- * gzip declarations
- */
-
-#define OF(args)  args
-#define STATIC static
-
-#undef memset
-#undef memcpy
-#define memzero(s, n)     memset ((s), 0, (n))
-
-typedef unsigned char  uch;
-typedef unsigned short ush;
-typedef unsigned long  ulg;
-
-#define WSIZE 0x8000		/* Window size must be at least 32k, */
-				/* and a power of two */
-
-static uch *inbuf;	     /* input buffer */
-static uch window[WSIZE];    /* Sliding window buffer */
-
-static unsigned insize = 0;  /* valid bytes in inbuf */
-static unsigned inptr = 0;   /* index of next byte to be processed in inbuf */
-static unsigned outcnt = 0;  /* bytes in output buffer */
-
-/* gzip flag byte */
-#define ASCII_FLAG   0x01 /* bit 0 set: file probably ASCII text */
-#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
-#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
-#define ORIG_NAME    0x08 /* bit 3 set: original file name present */
-#define COMMENT      0x10 /* bit 4 set: file comment present */
-#define ENCRYPTED    0x20 /* bit 5 set: file is encrypted */
-#define RESERVED     0xC0 /* bit 6,7:   reserved */
-
-#define get_byte()  (inptr < insize ? inbuf[inptr++] : fill_inbuf())
-
-/* Diagnostic functions */
-#ifdef DEBUG
-#  define Assert(cond,msg) {if(!(cond)) error(msg);}
-#  define Trace(x) fprintf x
-#  define Tracev(x) {if (verbose) fprintf x ;}
-#  define Tracevv(x) {if (verbose>1) fprintf x ;}
-#  define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
-#  define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
-#else
-#  define Assert(cond,msg)
-#  define Trace(x)
-#  define Tracev(x)
-#  define Tracevv(x)
-#  define Tracec(c,x)
-#  define Tracecv(c,x)
-#endif
-
-static int  fill_inbuf(void);
-static void flush_window(void);
-static void error(char *m);
-
-extern char input_data[];
-extern int input_len;
-
-static long bytes_out = 0;
-static uch *output_data;
-static unsigned long output_ptr = 0;
-
-static void error(char *m);
-
-int puts(const char *);
-
-extern int _text;		/* Defined in vmlinux.lds.S */
-extern int _end;
-static unsigned long free_mem_ptr;
-static unsigned long free_mem_end_ptr;
-
-#define HEAP_SIZE             0x10000
-
-#include "../../../../lib/inflate.c"
-
-#ifdef CONFIG_SH_STANDARD_BIOS
-size_t strlen(const char *s)
-{
-	int i = 0;
-
-	while (*s++)
-		i++;
-	return i;
-}
-
-int puts(const char *s)
-{
-	int len = strlen(s);
-	sh_bios_console_write(s, len);
-	return len;
-}
-#else
-int puts(const char *s)
-{
-	/* This should be updated to use the sh-sci routines */
-	return 0;
-}
-#endif
-
-void* memset(void* s, int c, size_t n)
-{
-	int i;
-	char *ss = (char*)s;
-
-	for (i=0;i<n;i++) ss[i] = c;
-	return s;
-}
-
-void* memcpy(void* __dest, __const void* __src,
-			    size_t __n)
-{
-	int i;
-	char *d = (char *)__dest, *s = (char *)__src;
-
-	for (i=0;i<__n;i++) d[i] = s[i];
-	return __dest;
-}
-
-/* ===========================================================================
- * Fill the input buffer. This is called only when the buffer is empty
- * and at least one byte is really needed.
- */
-static int fill_inbuf(void)
-{
-	if (insize != 0) {
-		error("ran out of input data");
-	}
-
-	inbuf = input_data;
-	insize = input_len;
-	inptr = 1;
-	return inbuf[0];
-}
-
-/* ===========================================================================
- * Write the output window window[0..outcnt-1] and update crc and bytes_out.
- * (Used for the decompressed data only.)
- */
-static void flush_window(void)
-{
-    ulg c = crc;         /* temporary variable */
-    unsigned n;
-    uch *in, *out, ch;
-
-    in = window;
-    out = &output_data[output_ptr];
-    for (n = 0; n < outcnt; n++) {
-	    ch = *out++ = *in++;
-	    c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
-    }
-    crc = c;
-    bytes_out += (ulg)outcnt;
-    output_ptr += (ulg)outcnt;
-    outcnt = 0;
-}
-
-static void error(char *x)
-{
-	puts("\n\n");
-	puts(x);
-	puts("\n\n -- System halted");
-
-	while(1);	/* Halt */
-}
-
-#define STACK_SIZE (4096)
-long user_stack [STACK_SIZE];
-long* stack_start = &user_stack[STACK_SIZE];
-
-void decompress_kernel(void)
-{
-	output_data = NULL;
-	output_ptr = PHYSADDR((unsigned long)&_text+PAGE_SIZE);
-#ifdef CONFIG_29BIT
-	output_ptr |= P2SEG;
-#endif
-	free_mem_ptr = (unsigned long)&_end;
-	free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;
-
-	makecrc();
-	puts("Uncompressing Linux... ");
-	gunzip();
-	puts("Ok, booting the kernel.\n");
-}
diff --git a/arch/sh/boot/compressed/misc_64.c b/arch/sh/boot/compressed/misc_64.c
deleted file mode 100644
index 2941657e18aa..000000000000
--- a/arch/sh/boot/compressed/misc_64.c
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * arch/sh/boot/compressed/misc_64.c
- *
- * This is a collection of several routines from gzip-1.0.3
- * adapted for Linux.
- *
- * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
- *
- * Adapted for SHmedia from sh by Stuart Menefy, May 2002
- */
-
-#include <asm/uaccess.h>
-
-/* cache.c */
-#define CACHE_ENABLE      0
-#define CACHE_DISABLE     1
-int cache_control(unsigned int command);
-
-/*
- * gzip declarations
- */
-
-#define OF(args)  args
-#define STATIC static
-
-#undef memset
-#undef memcpy
-#define memzero(s, n)     memset ((s), 0, (n))
-
-typedef unsigned char uch;
-typedef unsigned short ush;
-typedef unsigned long ulg;
-
-#define WSIZE 0x8000		/* Window size must be at least 32k, */
-				/* and a power of two */
-
-static uch *inbuf;		/* input buffer */
-static uch window[WSIZE];	/* Sliding window buffer */
-
-static unsigned insize = 0;	/* valid bytes in inbuf */
-static unsigned inptr = 0;	/* index of next byte to be processed in inbuf */
-static unsigned outcnt = 0;	/* bytes in output buffer */
-
-/* gzip flag byte */
-#define ASCII_FLAG   0x01	/* bit 0 set: file probably ASCII text */
-#define CONTINUATION 0x02	/* bit 1 set: continuation of multi-part gzip file */
-#define EXTRA_FIELD  0x04	/* bit 2 set: extra field present */
-#define ORIG_NAME    0x08	/* bit 3 set: original file name present */
-#define COMMENT      0x10	/* bit 4 set: file comment present */
-#define ENCRYPTED    0x20	/* bit 5 set: file is encrypted */
-#define RESERVED     0xC0	/* bit 6,7:   reserved */
-
-#define get_byte()  (inptr < insize ? inbuf[inptr++] : fill_inbuf())
-
-/* Diagnostic functions */
-#ifdef DEBUG
-#  define Assert(cond,msg) {if(!(cond)) error(msg);}
-#  define Trace(x) fprintf x
-#  define Tracev(x) {if (verbose) fprintf x ;}
-#  define Tracevv(x) {if (verbose>1) fprintf x ;}
-#  define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
-#  define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
-#else
-#  define Assert(cond,msg)
-#  define Trace(x)
-#  define Tracev(x)
-#  define Tracevv(x)
-#  define Tracec(c,x)
-#  define Tracecv(c,x)
-#endif
-
-static int fill_inbuf(void);
-static void flush_window(void);
-static void error(char *m);
-
-extern char input_data[];
-extern int input_len;
-
-static long bytes_out = 0;
-static uch *output_data;
-static unsigned long output_ptr = 0;
-
-static void error(char *m);
-
-static void puts(const char *);
-
-extern int _text;		/* Defined in vmlinux.lds.S */
-extern int _end;
-static unsigned long free_mem_ptr;
-static unsigned long free_mem_end_ptr;
-
-#define HEAP_SIZE             0x10000
-
-#include "../../../../lib/inflate.c"
-
-void puts(const char *s)
-{
-}
-
-void *memset(void *s, int c, size_t n)
-{
-	int i;
-	char *ss = (char *) s;
-
-	for (i = 0; i < n; i++)
-		ss[i] = c;
-	return s;
-}
-
-void *memcpy(void *__dest, __const void *__src, size_t __n)
-{
-	int i;
-	char *d = (char *) __dest, *s = (char *) __src;
-
-	for (i = 0; i < __n; i++)
-		d[i] = s[i];
-	return __dest;
-}
-
-/* ===========================================================================
- * Fill the input buffer. This is called only when the buffer is empty
- * and at least one byte is really needed.
- */
-static int fill_inbuf(void)
-{
-	if (insize != 0) {
-		error("ran out of input data\n");
-	}
-
-	inbuf = input_data;
-	insize = input_len;
-	inptr = 1;
-	return inbuf[0];
-}
-
-/* ===========================================================================
- * Write the output window window[0..outcnt-1] and update crc and bytes_out.
- * (Used for the decompressed data only.)
- */
-static void flush_window(void)
-{
-	ulg c = crc;		/* temporary variable */
-	unsigned n;
-	uch *in, *out, ch;
-
-	in = window;
-	out = &output_data[output_ptr];
-	for (n = 0; n < outcnt; n++) {
-		ch = *out++ = *in++;
-		c = crc_32_tab[((int) c ^ ch) & 0xff] ^ (c >> 8);
-	}
-	crc = c;
-	bytes_out += (ulg) outcnt;
-	output_ptr += (ulg) outcnt;
-	outcnt = 0;
-	puts(".");
-}
-
-static void error(char *x)
-{
-	puts("\n\n");
-	puts(x);
-	puts("\n\n -- System halted");
-
-	while (1) ;		/* Halt */
-}
-
-#define STACK_SIZE (4096)
-long __attribute__ ((aligned(8))) user_stack[STACK_SIZE];
-long *stack_start = &user_stack[STACK_SIZE];
-
-void decompress_kernel(void)
-{
-	output_data = (uch *) (CONFIG_MEMORY_START + 0x2000);
-	free_mem_ptr = (unsigned long) &_end;
-	free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;
-
-	makecrc();
-	puts("Uncompressing Linux... ");
-	cache_control(CACHE_ENABLE);
-	gunzip();
-	puts("\n");
-
-#if 0
-	/* When booting from ROM may want to do something like this if the
-	 * boot loader doesn't.
-	 */
-
-	/* Set up the parameters and command line */
-	{
-		volatile unsigned int *parambase =
-		    (int *) (CONFIG_MEMORY_START + 0x1000);
-
-		parambase[0] = 0x1;	/* MOUNT_ROOT_RDONLY */
-		parambase[1] = 0x0;	/* RAMDISK_FLAGS */
-		parambase[2] = 0x0200;	/* ORIG_ROOT_DEV */
-		parambase[3] = 0x0;	/* LOADER_TYPE */
-		parambase[4] = 0x0;	/* INITRD_START */
-		parambase[5] = 0x0;	/* INITRD_SIZE */
-		parambase[6] = 0;
-
-		strcpy((char *) ((int) parambase + 0x100),
-		       "console=ttySC0,38400");
-	}
-#endif
-
-	puts("Ok, booting the kernel.\n");
-
-	cache_control(CACHE_DISABLE);
-}
diff --git a/arch/sh/boot/compressed/piggy.S b/arch/sh/boot/compressed/piggy.S
deleted file mode 100644
index 566071926b13..000000000000
--- a/arch/sh/boot/compressed/piggy.S
+++ /dev/null
@@ -1,8 +0,0 @@
-	.global	input_len, input_data
-	.data
-input_len:
-	.long	input_data_end - input_data
-input_data:
-	.incbin	"arch/sh/boot/compressed/vmlinux.bin.gz"
-input_data_end:
-	.end
diff --git a/arch/sh/boot/compressed/vmlinux.scr b/arch/sh/boot/compressed/vmlinux.scr
new file mode 100644
index 000000000000..f02382ae5c48
--- /dev/null
+++ b/arch/sh/boot/compressed/vmlinux.scr
@@ -0,0 +1,10 @@
+SECTIONS
+{
+  .rodata.compressed : {
+	input_len = .;
+	LONG(input_data_end - input_data) input_data = .;
+	*(.data)
+	output_len = . - 4;
+	input_data_end = .;
+	}
+}
diff --git a/arch/sh/boot/romimage/Makefile b/arch/sh/boot/romimage/Makefile
new file mode 100644
index 000000000000..5806eee84f6f
--- /dev/null
+++ b/arch/sh/boot/romimage/Makefile
@@ -0,0 +1,19 @@
+#
+# linux/arch/sh/boot/romimage/Makefile
+#
+# create an image suitable for burning to flash from zImage
+#
+
+targets		:= vmlinux head.o
+
+OBJECTS = $(obj)/head.o
+LDFLAGS_vmlinux := --oformat $(ld-bfd) -Ttext 0 -e romstart
+
+$(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o FORCE
+	$(call if_changed,ld)
+	@:
+
+LDFLAGS_piggy.o := -r --format binary --oformat $(ld-bfd) -T
+
+$(obj)/piggy.o: $(obj)/vmlinux.scr arch/sh/boot/zImage FORCE
+	$(call if_changed,ld)
diff --git a/arch/sh/boot/romimage/head.S b/arch/sh/boot/romimage/head.S
new file mode 100644
index 000000000000..219bc626dd71
--- /dev/null
+++ b/arch/sh/boot/romimage/head.S
@@ -0,0 +1,10 @@
+/*
+ *  linux/arch/sh/boot/romimage/head.S
+ *
+ * Board specific setup code, executed before zImage loader
+ */
+
+.text
+	.global	romstart
+romstart:
+#include <mach/romimage.h>
diff --git a/arch/sh/boot/romimage/vmlinux.scr b/arch/sh/boot/romimage/vmlinux.scr
new file mode 100644
index 000000000000..287c08f8b4bb
--- /dev/null
+++ b/arch/sh/boot/romimage/vmlinux.scr
@@ -0,0 +1,6 @@
+SECTIONS
+{
+  .text : {
+	*(.data)
+	}
+}
diff --git a/arch/sh/configs/kfr2r09_defconfig b/arch/sh/configs/kfr2r09_defconfig
new file mode 100644
index 000000000000..90e575c34d58
--- /dev/null
+++ b/arch/sh/configs/kfr2r09_defconfig
@@ -0,0 +1,877 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.31-rc3
+# Thu Jul 23 17:45:09 2009
+#
+CONFIG_SUPERH=y
+CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
+CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_IRQ_PER_CPU=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_SYS_SUPPORTS_CMT=y
+CONFIG_SYS_SUPPORTS_TMU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_ARCH_NO_VIRT_TO_BUS=y
+CONFIG_ARCH_HAS_DEFAULT_IDLE=y
+CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_BZIP2=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
+CONFIG_COMPAT_BRK=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+# CONFIG_MODULES is not set
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+# CONFIG_FREEZER is not set
+
+#
+# System type
+#
+CONFIG_CPU_SH4=y
+CONFIG_CPU_SH4A=y
+CONFIG_CPU_SHX2=y
+CONFIG_ARCH_SHMOBILE=y
+# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7201 is not set
+# CONFIG_CPU_SUBTYPE_SH7203 is not set
+# CONFIG_CPU_SUBTYPE_SH7206 is not set
+# CONFIG_CPU_SUBTYPE_SH7263 is not set
+# CONFIG_CPU_SUBTYPE_MXG is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7706 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+# CONFIG_CPU_SUBTYPE_SH7710 is not set
+# CONFIG_CPU_SUBTYPE_SH7712 is not set
+# CONFIG_CPU_SUBTYPE_SH7720 is not set
+# CONFIG_CPU_SUBTYPE_SH7721 is not set
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7751R is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+# CONFIG_CPU_SUBTYPE_SH7723 is not set
+CONFIG_CPU_SUBTYPE_SH7724=y
+# CONFIG_CPU_SUBTYPE_SH7763 is not set
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+# CONFIG_CPU_SUBTYPE_SH7780 is not set
+# CONFIG_CPU_SUBTYPE_SH7785 is not set
+# CONFIG_CPU_SUBTYPE_SH7786 is not set
+# CONFIG_CPU_SUBTYPE_SHX3 is not set
+# CONFIG_CPU_SUBTYPE_SH7343 is not set
+# CONFIG_CPU_SUBTYPE_SH7722 is not set
+# CONFIG_CPU_SUBTYPE_SH7366 is not set
+
+#
+# Memory management options
+#
+CONFIG_QUICKLIST=y
+CONFIG_MMU=y
+CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_MEMORY_START=0x08000000
+CONFIG_MEMORY_SIZE=0x08000000
+CONFIG_29BIT=y
+# CONFIG_X2TLB is not set
+CONFIG_VSYSCALL=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_MAX_ACTIVE_REGIONS=1
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_SPARSEMEM_STATIC=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=2
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+
+#
+# Cache configuration
+#
+CONFIG_CACHE_WRITEBACK=y
+# CONFIG_CACHE_WRITETHROUGH is not set
+# CONFIG_CACHE_OFF is not set
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_SH_FPU=y
+# CONFIG_SH_STORE_QUEUES is not set
+CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_SR_RB=y
+CONFIG_CPU_HAS_FPU=y
+
+#
+# Board support
+#
+# CONFIG_SH_7724_SOLUTION_ENGINE is not set
+CONFIG_SH_KFR2R09=y
+
+#
+# Timer and clock configuration
+#
+# CONFIG_SH_TIMER_TMU is not set
+CONFIG_SH_TIMER_CMT=y
+CONFIG_SH_PCLK_FREQ=33333333
+CONFIG_SH_CLK_CPG=y
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+
+#
+# Additional SuperH Device Drivers
+#
+# CONFIG_HEARTBEAT is not set
+# CONFIG_PUSH_SWITCH is not set
+
+#
+# Kernel features
+#
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+CONFIG_HZ_1000=y
+CONFIG_HZ=1000
+# CONFIG_SCHED_HRTICK is not set
+CONFIG_KEXEC=y
+# CONFIG_CRASH_DUMP is not set
+# CONFIG_SECCOMP is not set
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+CONFIG_GUSA=y
+# CONFIG_SPARSE_IRQ is not set
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_ENTRY_OFFSET=0x00001000
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttySC1,115200"
+
+#
+# Bus options
+#
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+# CONFIG_SUSPEND is not set
+# CONFIG_HIBERNATION is not set
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+# CONFIG_MTD_UBI_GLUEBI is not set
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_NETDEVICES is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_KEYBOARD_MATRIX is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+CONFIG_KEYBOARD_SH_KEYSC=y
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=6
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+# CONFIG_I2C_CHARDEV is not set
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_DESIGNWARE is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_SH_MOBILE=y
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_SOUND is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+CONFIG_UIO=y
+# CONFIG_UIO_PDRV is not set
+CONFIG_UIO_PDRV_GENIRQ=y
+# CONFIG_UIO_SMX is not set
+# CONFIG_UIO_SERCOS3 is not set
+
+#
+# TI VLYNQ
+#
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+# CONFIG_FSNOTIFY is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+# CONFIG_MISC_FILESYSTEMS is not set
+# CONFIG_NETWORK_FILESYSTEMS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_NLS is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_FTRACE_SYSCALLS=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+CONFIG_CRC7=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_HAVE_LMB=y
+CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff --git a/arch/sh/include/asm/device.h b/arch/sh/include/asm/device.h
index 8688a88303ee..783ecdc64e25 100644
--- a/arch/sh/include/asm/device.h
+++ b/arch/sh/include/asm/device.h
@@ -3,7 +3,9 @@
  *
  * This file is released under the GPLv2
  */
-#include <asm-generic/device.h>
+
+struct dev_archdata {
+};
 
 struct platform_device;
 /* allocate contiguous memory chunk and fill in struct resource */
@@ -12,3 +14,6 @@ int platform_resource_setup_memory(struct platform_device *pdev,
 
 void plat_early_device_setup(void);
 
+struct pdev_archdata {
+	int hwblk_id;
+};
diff --git a/arch/sh/include/asm/dma-sh.h b/arch/sh/include/asm/dma-sh.h
index 0c8f8e14622a..68a5f4cb0343 100644
--- a/arch/sh/include/asm/dma-sh.h
+++ b/arch/sh/include/asm/dma-sh.h
@@ -16,6 +16,7 @@
 
 /* DMAOR contorl: The DMAOR access size is different by CPU.*/
 #if defined(CONFIG_CPU_SUBTYPE_SH7723)	|| \
+    defined(CONFIG_CPU_SUBTYPE_SH7724)	|| \
     defined(CONFIG_CPU_SUBTYPE_SH7780)	|| \
     defined(CONFIG_CPU_SUBTYPE_SH7785)
 #define dmaor_read_reg(n) \
diff --git a/arch/sh/include/asm/dwarf.h b/arch/sh/include/asm/dwarf.h
new file mode 100644
index 000000000000..60b180728d8d
--- /dev/null
+++ b/arch/sh/include/asm/dwarf.h
@@ -0,0 +1,402 @@
+/*
+ * Copyright (C) 2009 Matt Fleming <matt@console-pimps.org>
+ *
+ * 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.
+ *
+ */
+#ifndef __ASM_SH_DWARF_H
+#define __ASM_SH_DWARF_H
+
+#ifdef CONFIG_DWARF_UNWINDER
+
+/*
+ * DWARF expression operations
+ */
+#define DW_OP_addr	0x03
+#define DW_OP_deref	0x06
+#define DW_OP_const1u	0x08
+#define DW_OP_const1s	0x09
+#define DW_OP_const2u	0x0a
+#define DW_OP_const2s	0x0b
+#define DW_OP_const4u	0x0c
+#define DW_OP_const4s	0x0d
+#define DW_OP_const8u	0x0e
+#define DW_OP_const8s	0x0f
+#define DW_OP_constu	0x10
+#define DW_OP_consts	0x11
+#define DW_OP_dup	0x12
+#define DW_OP_drop	0x13
+#define DW_OP_over	0x14
+#define DW_OP_pick	0x15
+#define DW_OP_swap	0x16
+#define DW_OP_rot	0x17
+#define DW_OP_xderef	0x18
+#define DW_OP_abs	0x19
+#define DW_OP_and	0x1a
+#define DW_OP_div	0x1b
+#define DW_OP_minus	0x1c
+#define DW_OP_mod	0x1d
+#define DW_OP_mul	0x1e
+#define DW_OP_neg	0x1f
+#define DW_OP_not	0x20
+#define DW_OP_or	0x21
+#define DW_OP_plus	0x22
+#define DW_OP_plus_uconst	0x23
+#define DW_OP_shl	0x24
+#define DW_OP_shr	0x25
+#define DW_OP_shra	0x26
+#define DW_OP_xor	0x27
+#define DW_OP_skip	0x2f
+#define DW_OP_bra	0x28
+#define DW_OP_eq	0x29
+#define DW_OP_ge	0x2a
+#define DW_OP_gt	0x2b
+#define DW_OP_le	0x2c
+#define DW_OP_lt	0x2d
+#define DW_OP_ne	0x2e
+#define DW_OP_lit0	0x30
+#define DW_OP_lit1	0x31
+#define DW_OP_lit2	0x32
+#define DW_OP_lit3	0x33
+#define DW_OP_lit4	0x34
+#define DW_OP_lit5	0x35
+#define DW_OP_lit6	0x36
+#define DW_OP_lit7	0x37
+#define DW_OP_lit8	0x38
+#define DW_OP_lit9	0x39
+#define DW_OP_lit10	0x3a
+#define DW_OP_lit11	0x3b
+#define DW_OP_lit12	0x3c
+#define DW_OP_lit13	0x3d
+#define DW_OP_lit14	0x3e
+#define DW_OP_lit15	0x3f
+#define DW_OP_lit16	0x40
+#define DW_OP_lit17	0x41
+#define DW_OP_lit18	0x42
+#define DW_OP_lit19	0x43
+#define DW_OP_lit20	0x44
+#define DW_OP_lit21	0x45
+#define DW_OP_lit22	0x46
+#define DW_OP_lit23	0x47
+#define DW_OP_lit24	0x48
+#define DW_OP_lit25	0x49
+#define DW_OP_lit26	0x4a
+#define DW_OP_lit27	0x4b
+#define DW_OP_lit28	0x4c
+#define DW_OP_lit29	0x4d
+#define DW_OP_lit30	0x4e
+#define DW_OP_lit31	0x4f
+#define DW_OP_reg0	0x50
+#define DW_OP_reg1	0x51
+#define DW_OP_reg2	0x52
+#define DW_OP_reg3	0x53
+#define DW_OP_reg4	0x54
+#define DW_OP_reg5	0x55
+#define DW_OP_reg6	0x56
+#define DW_OP_reg7	0x57
+#define DW_OP_reg8	0x58
+#define DW_OP_reg9	0x59
+#define DW_OP_reg10	0x5a
+#define DW_OP_reg11	0x5b
+#define DW_OP_reg12	0x5c
+#define DW_OP_reg13	0x5d
+#define DW_OP_reg14	0x5e
+#define DW_OP_reg15	0x5f
+#define DW_OP_reg16	0x60
+#define DW_OP_reg17	0x61
+#define DW_OP_reg18	0x62
+#define DW_OP_reg19	0x63
+#define DW_OP_reg20	0x64
+#define DW_OP_reg21	0x65
+#define DW_OP_reg22	0x66
+#define DW_OP_reg23	0x67
+#define DW_OP_reg24	0x68
+#define DW_OP_reg25	0x69
+#define DW_OP_reg26	0x6a
+#define DW_OP_reg27	0x6b
+#define DW_OP_reg28	0x6c
+#define DW_OP_reg29	0x6d
+#define DW_OP_reg30	0x6e
+#define DW_OP_reg31	0x6f
+#define DW_OP_breg0	0x70
+#define DW_OP_breg1	0x71
+#define DW_OP_breg2	0x72
+#define DW_OP_breg3	0x73
+#define DW_OP_breg4	0x74
+#define DW_OP_breg5	0x75
+#define DW_OP_breg6	0x76
+#define DW_OP_breg7	0x77
+#define DW_OP_breg8	0x78
+#define DW_OP_breg9	0x79
+#define DW_OP_breg10	0x7a
+#define DW_OP_breg11	0x7b
+#define DW_OP_breg12	0x7c
+#define DW_OP_breg13	0x7d
+#define DW_OP_breg14	0x7e
+#define DW_OP_breg15	0x7f
+#define DW_OP_breg16	0x80
+#define DW_OP_breg17	0x81
+#define DW_OP_breg18	0x82
+#define DW_OP_breg19	0x83
+#define DW_OP_breg20	0x84
+#define DW_OP_breg21	0x85
+#define DW_OP_breg22	0x86
+#define DW_OP_breg23	0x87
+#define DW_OP_breg24	0x88
+#define DW_OP_breg25	0x89
+#define DW_OP_breg26	0x8a
+#define DW_OP_breg27	0x8b
+#define DW_OP_breg28	0x8c
+#define DW_OP_breg29	0x8d
+#define DW_OP_breg30	0x8e
+#define DW_OP_breg31	0x8f
+#define DW_OP_regx	0x90
+#define DW_OP_fbreg	0x91
+#define DW_OP_bregx	0x92
+#define DW_OP_piece	0x93
+#define DW_OP_deref_size	0x94
+#define DW_OP_xderef_size	0x95
+#define DW_OP_nop	0x96
+#define DW_OP_push_object_address	0x97
+#define DW_OP_call2	0x98
+#define DW_OP_call4	0x99
+#define DW_OP_call_ref	0x9a
+#define DW_OP_form_tls_address	0x9b
+#define DW_OP_call_frame_cfa	0x9c
+#define DW_OP_bit_piece	0x9d
+#define DW_OP_lo_user	0xe0
+#define DW_OP_hi_user	0xff
+
+/*
+ * Addresses used in FDE entries in the .eh_frame section may be encoded
+ * using one of the following encodings.
+ */
+#define DW_EH_PE_absptr	0x00
+#define DW_EH_PE_omit	0xff
+#define DW_EH_PE_uleb128	0x01
+#define DW_EH_PE_udata2	0x02
+#define DW_EH_PE_udata4	0x03
+#define DW_EH_PE_udata8	0x04
+#define DW_EH_PE_sleb128	0x09
+#define DW_EH_PE_sdata2	0x0a
+#define DW_EH_PE_sdata4	0x0b
+#define DW_EH_PE_sdata8	0x0c
+#define DW_EH_PE_signed	0x09
+
+#define DW_EH_PE_pcrel	0x10
+
+/*
+ * The architecture-specific register number that contains the return
+ * address in the .debug_frame table.
+ */
+#define DWARF_ARCH_RA_REG	17
+
+#ifndef __ASSEMBLY__
+/*
+ * Read either the frame pointer (r14) or the stack pointer (r15).
+ * NOTE: this MUST be inlined.
+ */
+static __always_inline unsigned long dwarf_read_arch_reg(unsigned int reg)
+{
+	unsigned long value;
+
+	switch (reg) {
+	case 14:
+		__asm__ __volatile__("mov r14, %0\n" : "=r" (value));
+		break;
+	case 15:
+		__asm__ __volatile__("mov r15, %0\n" : "=r" (value));
+		break;
+	default:
+		BUG();
+	}
+
+	return value;
+}
+
+/**
+ *	dwarf_cie - Common Information Entry
+ */
+struct dwarf_cie {
+	unsigned long length;
+	unsigned long cie_id;
+	unsigned char version;
+	const char *augmentation;
+	unsigned int code_alignment_factor;
+	int data_alignment_factor;
+
+	/* Which column in the rule table represents return addr of func. */
+	unsigned int return_address_reg;
+
+	unsigned char *initial_instructions;
+	unsigned char *instructions_end;
+
+	unsigned char encoding;
+
+	unsigned long cie_pointer;
+
+	struct list_head link;
+
+	unsigned long flags;
+#define DWARF_CIE_Z_AUGMENTATION	(1 << 0)
+};
+
+/**
+ *	dwarf_fde - Frame Description Entry
+ */
+struct dwarf_fde {
+	unsigned long length;
+	unsigned long cie_pointer;
+	struct dwarf_cie *cie;
+	unsigned long initial_location;
+	unsigned long address_range;
+	unsigned char *instructions;
+	unsigned char *end;
+	struct list_head link;
+};
+
+/**
+ *	dwarf_frame - DWARF information for a frame in the call stack
+ */
+struct dwarf_frame {
+	struct dwarf_frame *prev, *next;
+
+	unsigned long pc;
+
+	struct dwarf_reg *regs;
+	unsigned int num_regs;	/* how many regs are allocated? */
+
+	unsigned int depth;	/* what level are we in the callstack? */
+
+	unsigned long cfa;
+
+	/* Valid when DW_FRAME_CFA_REG_OFFSET is set in flags */
+	unsigned int cfa_register;
+	unsigned int cfa_offset;
+
+	/* Valid when DW_FRAME_CFA_REG_EXP is set in flags */
+	unsigned char *cfa_expr;
+	unsigned int cfa_expr_len;
+
+	unsigned long flags;
+#define DWARF_FRAME_CFA_REG_OFFSET	(1 << 0)
+#define DWARF_FRAME_CFA_REG_EXP		(1 << 1)
+
+	unsigned long return_addr;
+};
+
+/**
+ *	dwarf_reg - DWARF register
+ *	@flags: Describes how to calculate the value of this register
+ */
+struct dwarf_reg {
+	unsigned long addr;
+	unsigned long flags;
+#define DWARF_REG_OFFSET	(1 << 0)
+};
+
+/**
+ *	dwarf_stack - a DWARF stack contains a collection of DWARF frames
+ *	@depth: the number of frames in the stack
+ *	@level: an array of DWARF frames, indexed by stack level
+ *
+ */
+struct dwarf_stack {
+	unsigned int depth;
+	struct dwarf_frame **level;
+};
+
+/*
+ * Call Frame instruction opcodes.
+ */
+#define DW_CFA_advance_loc	0x40
+#define DW_CFA_offset		0x80
+#define DW_CFA_restore		0xc0
+#define DW_CFA_nop		0x00
+#define DW_CFA_set_loc		0x01
+#define DW_CFA_advance_loc1	0x02
+#define DW_CFA_advance_loc2	0x03
+#define DW_CFA_advance_loc4	0x04
+#define DW_CFA_offset_extended	0x05
+#define DW_CFA_restore_extended	0x06
+#define DW_CFA_undefined	0x07
+#define DW_CFA_same_value	0x08
+#define DW_CFA_register		0x09
+#define DW_CFA_remember_state	0x0a
+#define DW_CFA_restore_state	0x0b
+#define DW_CFA_def_cfa		0x0c
+#define DW_CFA_def_cfa_register	0x0d
+#define DW_CFA_def_cfa_offset	0x0e
+#define DW_CFA_def_cfa_expression	0x0f
+#define DW_CFA_expression	0x10
+#define DW_CFA_offset_extended_sf	0x11
+#define DW_CFA_def_cfa_sf	0x12
+#define DW_CFA_def_cfa_offset_sf	0x13
+#define DW_CFA_val_offset	0x14
+#define DW_CFA_val_offset_sf	0x15
+#define DW_CFA_val_expression	0x16
+#define DW_CFA_lo_user		0x1c
+#define DW_CFA_hi_user		0x3f
+
+/*
+ * Some call frame instructions encode their operands in the opcode. We
+ * need some helper functions to extract both the opcode and operands
+ * from an instruction.
+ */
+static inline unsigned int DW_CFA_opcode(unsigned long insn)
+{
+	return (insn & 0xc0);
+}
+
+static inline unsigned int DW_CFA_operand(unsigned long insn)
+{
+	return (insn & 0x3f);
+}
+
+#define DW_EH_FRAME_CIE	0		/* .eh_frame CIE IDs are 0 */
+#define DW_CIE_ID	0xffffffff
+#define DW64_CIE_ID	0xffffffffffffffffULL
+
+/*
+ * DWARF FDE/CIE length field values.
+ */
+#define DW_EXT_LO	0xfffffff0
+#define DW_EXT_HI	0xffffffff
+#define DW_EXT_DWARF64	DW_EXT_HI
+
+extern void dwarf_unwinder_init(void);
+
+extern struct dwarf_frame *dwarf_unwind_stack(unsigned long,
+					      struct dwarf_frame *);
+#endif /* __ASSEMBLY__ */
+
+#define CFI_STARTPROC	.cfi_startproc
+#define CFI_ENDPROC	.cfi_endproc
+#define CFI_DEF_CFA	.cfi_def_cfa
+#define CFI_REGISTER	.cfi_register
+#define CFI_REL_OFFSET	.cfi_rel_offset
+
+#else
+
+/*
+ * Use the asm comment character to ignore the rest of the line.
+ */
+#define CFI_IGNORE	!
+
+#define CFI_STARTPROC	CFI_IGNORE
+#define CFI_ENDPROC	CFI_IGNORE
+#define CFI_DEF_CFA	CFI_IGNORE
+#define CFI_REGISTER	CFI_IGNORE
+#define CFI_REL_OFFSET	CFI_IGNORE
+
+#ifndef __ASSEMBLY__
+static inline void dwarf_unwinder_init(void)
+{
+}
+#endif
+
+#endif /* CONFIG_DWARF_UNWINDER */
+
+#endif /* __ASM_SH_DWARF_H */
diff --git a/arch/sh/include/asm/entry-macros.S b/arch/sh/include/asm/entry-macros.S
index 3a4752a65722..64fd0de24daf 100644
--- a/arch/sh/include/asm/entry-macros.S
+++ b/arch/sh/include/asm/entry-macros.S
@@ -31,8 +31,92 @@
 #endif	
 	.endm
 
+#ifdef CONFIG_TRACE_IRQFLAGS
+
+	.macro	TRACE_IRQS_ON
+	mov.l	r0, @-r15
+	mov.l	r1, @-r15
+	mov.l	r2, @-r15
+	mov.l	r3, @-r15
+	mov.l	r4, @-r15
+	mov.l	r5, @-r15
+	mov.l	r6, @-r15
+	mov.l	r7, @-r15
+
+	mov.l   7834f, r0
+	jsr	@r0
+	 nop
+
+	mov.l	@r15+, r7
+	mov.l	@r15+, r6
+	mov.l	@r15+, r5
+	mov.l	@r15+, r4
+	mov.l	@r15+, r3
+	mov.l	@r15+, r2
+	mov.l	@r15+, r1
+	mov.l	@r15+, r0
+	mov.l	7834f, r0
+
+	bra	7835f
+	 nop
+	.balign	4
+7834:	.long	trace_hardirqs_on
+7835:
+	.endm
+	.macro	TRACE_IRQS_OFF
+
+	mov.l	r0, @-r15
+	mov.l	r1, @-r15
+	mov.l	r2, @-r15
+	mov.l	r3, @-r15
+	mov.l	r4, @-r15
+	mov.l	r5, @-r15
+	mov.l	r6, @-r15
+	mov.l	r7, @-r15
+
+	mov.l	7834f, r0
+	jsr	@r0
+	 nop
+
+	mov.l	@r15+, r7
+	mov.l	@r15+, r6
+	mov.l	@r15+, r5
+	mov.l	@r15+, r4
+	mov.l	@r15+, r3
+	mov.l	@r15+, r2
+	mov.l	@r15+, r1
+	mov.l	@r15+, r0
+	mov.l	7834f, r0
+
+	bra	7835f
+	 nop
+	.balign	4
+7834:	.long	trace_hardirqs_off
+7835:
+	.endm
+
+#else
+	.macro	TRACE_IRQS_ON
+	.endm
+
+	.macro	TRACE_IRQS_OFF
+	.endm
+#endif
+
 #if defined(CONFIG_CPU_SH2A) || defined(CONFIG_CPU_SH4)
 # define PREF(x)	pref	@x
 #else
 # define PREF(x)	nop
 #endif
+
+	/*
+	 * Macro for use within assembly. Because the DWARF unwinder
+	 * needs to use the frame register to unwind the stack, we
+	 * need to setup r14 with the value of the stack pointer as
+	 * the return address is usually on the stack somewhere.
+	 */
+	.macro	setup_frame_reg
+#ifdef CONFIG_DWARF_UNWINDER
+	mov	r15, r14
+#endif
+	.endm
diff --git a/arch/sh/include/asm/ftrace.h b/arch/sh/include/asm/ftrace.h
index 8fea7d8c8258..7e0bcc4d4a96 100644
--- a/arch/sh/include/asm/ftrace.h
+++ b/arch/sh/include/asm/ftrace.h
@@ -11,10 +11,13 @@ extern void mcount(void);
 #define MCOUNT_ADDR		((long)(mcount))
 
 #ifdef CONFIG_DYNAMIC_FTRACE
-#define CALLER_ADDR		((long)(ftrace_caller))
+#define CALL_ADDR		((long)(ftrace_call))
 #define STUB_ADDR		((long)(ftrace_stub))
+#define GRAPH_ADDR		((long)(ftrace_graph_call))
+#define CALLER_ADDR		((long)(ftrace_caller))
 
-#define MCOUNT_INSN_OFFSET	((STUB_ADDR - CALLER_ADDR) >> 1)
+#define MCOUNT_INSN_OFFSET	((STUB_ADDR - CALL_ADDR) - 4)
+#define GRAPH_INSN_OFFSET	((CALLER_ADDR - GRAPH_ADDR) - 4)
 
 struct dyn_arch_ftrace {
 	/* No extra data needed on sh */
diff --git a/arch/sh/include/asm/hardirq.h b/arch/sh/include/asm/hardirq.h
index 715ee237fc77..a5be4afa790b 100644
--- a/arch/sh/include/asm/hardirq.h
+++ b/arch/sh/include/asm/hardirq.h
@@ -1,16 +1,9 @@
 #ifndef __ASM_SH_HARDIRQ_H
 #define __ASM_SH_HARDIRQ_H
 
-#include <linux/threads.h>
-#include <linux/irq.h>
-
-/* entry.S is sensitive to the offsets of these fields */
-typedef struct {
-	unsigned int __softirq_pending;
-} ____cacheline_aligned irq_cpustat_t;
-
-#include <linux/irq_cpustat.h>	/* Standard mappings for irq_cpustat_t above */
-
 extern void ack_bad_irq(unsigned int irq);
+#define ack_bad_irq ack_bad_irq
+
+#include <asm-generic/hardirq.h>
 
 #endif /* __ASM_SH_HARDIRQ_H */
diff --git a/arch/sh/include/asm/hwblk.h b/arch/sh/include/asm/hwblk.h
new file mode 100644
index 000000000000..c01d72cb6757
--- /dev/null
+++ b/arch/sh/include/asm/hwblk.h
@@ -0,0 +1,70 @@
+#ifndef __ASM_SH_HWBLK_H
+#define __ASM_SH_HWBLK_H
+
+#include <asm/clock.h>
+#include <asm/io.h>
+
+#define HWBLK_CNT_USAGE 0
+#define HWBLK_CNT_NR 1
+
+#define HWBLK_AREA_FLAG_PARENT (1 << 0) /* valid parent */
+
+#define HWBLK_AREA(_flags, _parent)		\
+{						\
+	.flags = _flags,			\
+	.parent = _parent,			\
+}
+
+struct hwblk_area {
+	int cnt[HWBLK_CNT_NR];
+	unsigned char parent;
+	unsigned char flags;
+};
+
+#define HWBLK(_mstp, _bit, _area)		\
+{						\
+	.mstp = (void __iomem *)_mstp,		\
+	.bit = _bit,				\
+	.area = _area,				\
+}
+
+struct hwblk {
+	void __iomem *mstp;
+	unsigned char bit;
+	unsigned char area;
+	int cnt[HWBLK_CNT_NR];
+};
+
+struct hwblk_info {
+	struct hwblk_area *areas;
+	int nr_areas;
+	struct hwblk *hwblks;
+	int nr_hwblks;
+};
+
+/* Should be defined by processor-specific code */
+int arch_hwblk_init(void);
+int arch_hwblk_sleep_mode(void);
+
+int hwblk_register(struct hwblk_info *info);
+int hwblk_init(void);
+
+void hwblk_enable(struct hwblk_info *info, int hwblk);
+void hwblk_disable(struct hwblk_info *info, int hwblk);
+
+void hwblk_cnt_inc(struct hwblk_info *info, int hwblk, int cnt);
+void hwblk_cnt_dec(struct hwblk_info *info, int hwblk, int cnt);
+
+/* allow clocks to enable and disable hardware blocks */
+#define SH_HWBLK_CLK(_name, _id, _parent, _hwblk, _flags)	\
+{							\
+	.name		= _name,			\
+	.id		= _id,				\
+	.parent		= _parent,			\
+	.arch_flags	= _hwblk,			\
+	.flags		= _flags,			\
+}
+
+int sh_hwblk_clk_register(struct clk *clks, int nr);
+
+#endif /* __ASM_SH_HWBLK_H */
diff --git a/arch/sh/include/asm/lmb.h b/arch/sh/include/asm/lmb.h
new file mode 100644
index 000000000000..9b437f657ffa
--- /dev/null
+++ b/arch/sh/include/asm/lmb.h
@@ -0,0 +1,6 @@
+#ifndef __ASM_SH_LMB_H
+#define __ASM_SH_LMB_H
+
+#define LMB_REAL_LIMIT	0
+
+#endif /* __ASM_SH_LMB_H */
diff --git a/arch/sh/include/asm/pgtable_32.h b/arch/sh/include/asm/pgtable_32.h
index 72ea209195bd..0db19db913c7 100644
--- a/arch/sh/include/asm/pgtable_32.h
+++ b/arch/sh/include/asm/pgtable_32.h
@@ -20,7 +20,7 @@
  * - Bit 9 is reserved by everyone and used by _PAGE_PROTNONE.
  *
  * - Bits 10 and 11 are low bits of the PPN that are reserved on >= 4K pages.
- *   Bit 10 is used for _PAGE_ACCESSED, bit 11 remains unused.
+ *   Bit 10 is used for _PAGE_ACCESSED, and bit 11 is used for _PAGE_SPECIAL.
  *
  * - On 29 bit platforms, bits 31 to 29 are used for the space attributes
  *   and timing control which (together with bit 0) are moved into the
@@ -52,6 +52,7 @@
 #define _PAGE_PROTNONE	0x200		/* software: if not present  */
 #define _PAGE_ACCESSED	0x400		/* software: page referenced */
 #define _PAGE_FILE	_PAGE_WT	/* software: pagecache or swap? */
+#define _PAGE_SPECIAL	0x800		/* software: special page */
 
 #define _PAGE_SZ_MASK	(_PAGE_SZ0 | _PAGE_SZ1)
 #define _PAGE_PR_MASK	(_PAGE_RW | _PAGE_USER)
@@ -148,8 +149,12 @@
 # define _PAGE_SZHUGE	(_PAGE_FLAGS_HARD)
 #endif
 
+/*
+ * Mask of bits that are to be preserved accross pgprot changes.
+ */
 #define _PAGE_CHG_MASK \
-	(PTE_MASK | _PAGE_ACCESSED | _PAGE_CACHABLE | _PAGE_DIRTY)
+	(PTE_MASK | _PAGE_ACCESSED | _PAGE_CACHABLE | \
+	 _PAGE_DIRTY | _PAGE_SPECIAL)
 
 #ifndef __ASSEMBLY__
 
@@ -328,7 +333,7 @@ static inline void set_pte(pte_t *ptep, pte_t pte)
 #define pte_dirty(pte)		((pte).pte_low & _PAGE_DIRTY)
 #define pte_young(pte)		((pte).pte_low & _PAGE_ACCESSED)
 #define pte_file(pte)		((pte).pte_low & _PAGE_FILE)
-#define pte_special(pte)	(0)
+#define pte_special(pte)	((pte).pte_low & _PAGE_SPECIAL)
 
 #ifdef CONFIG_X2TLB
 #define pte_write(pte)		((pte).pte_high & _PAGE_EXT_USER_WRITE)
@@ -358,8 +363,9 @@ PTE_BIT_FUNC(low, mkclean, &= ~_PAGE_DIRTY);
 PTE_BIT_FUNC(low, mkdirty, |= _PAGE_DIRTY);
 PTE_BIT_FUNC(low, mkold, &= ~_PAGE_ACCESSED);
 PTE_BIT_FUNC(low, mkyoung, |= _PAGE_ACCESSED);
+PTE_BIT_FUNC(low, mkspecial, |= _PAGE_SPECIAL);
 
-static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
+#define __HAVE_ARCH_PTE_SPECIAL
 
 /*
  * Macro and implementation to make a page protection as uncachable.
diff --git a/arch/sh/include/asm/sections.h b/arch/sh/include/asm/sections.h
index 01a4076a3719..a78701da775b 100644
--- a/arch/sh/include/asm/sections.h
+++ b/arch/sh/include/asm/sections.h
@@ -7,6 +7,7 @@ extern void __nosave_begin, __nosave_end;
 extern long __machvec_start, __machvec_end;
 extern char __uncached_start, __uncached_end;
 extern char _ebss[];
+extern char __start_eh_frame[], __stop_eh_frame[];
 
 #endif /* __ASM_SH_SECTIONS_H */
 
diff --git a/arch/sh/include/asm/stacktrace.h b/arch/sh/include/asm/stacktrace.h
new file mode 100644
index 000000000000..797018213718
--- /dev/null
+++ b/arch/sh/include/asm/stacktrace.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2009  Matt Fleming
+ *
+ * Based on:
+ *	The x86 implementation - arch/x86/include/asm/stacktrace.h
+ */
+#ifndef _ASM_SH_STACKTRACE_H
+#define _ASM_SH_STACKTRACE_H
+
+/* Generic stack tracer with callbacks */
+
+struct stacktrace_ops {
+	void (*warning)(void *data, char *msg);
+	/* msg must contain %s for the symbol */
+	void (*warning_symbol)(void *data, char *msg, unsigned long symbol);
+	void (*address)(void *data, unsigned long address, int reliable);
+	/* On negative return stop dumping */
+	int (*stack)(void *data, char *name);
+};
+
+void dump_trace(struct task_struct *tsk, struct pt_regs *regs,
+		unsigned long *stack,
+		const struct stacktrace_ops *ops, void *data);
+
+#endif /* _ASM_SH_STACKTRACE_H */
diff --git a/arch/sh/include/asm/suspend.h b/arch/sh/include/asm/suspend.h
index b1b995370e79..5c8ea28ff7a4 100644
--- a/arch/sh/include/asm/suspend.h
+++ b/arch/sh/include/asm/suspend.h
@@ -10,6 +10,15 @@ struct swsusp_arch_regs {
 	struct pt_regs user_regs;
 	unsigned long bank1_regs[8];
 };
+
+void sh_mobile_call_standby(unsigned long mode);
+
+#ifdef CONFIG_CPU_IDLE
+void sh_mobile_setup_cpuidle(void);
+#else
+static inline void sh_mobile_setup_cpuidle(void) {}
+#endif
+
 #endif
 
 /* flags passed to assembly suspend code */
diff --git a/arch/sh/include/asm/syscall_32.h b/arch/sh/include/asm/syscall_32.h
index 6f83f2cc45c1..7d80df4f09cb 100644
--- a/arch/sh/include/asm/syscall_32.h
+++ b/arch/sh/include/asm/syscall_32.h
@@ -65,6 +65,7 @@ static inline void syscall_get_arguments(struct task_struct *task,
 	case 3: args[2] = regs->regs[6];
 	case 2: args[1] = regs->regs[5];
 	case 1:	args[0] = regs->regs[4];
+	case 0:
 		break;
 	default:
 		BUG();
diff --git a/arch/sh/include/asm/thread_info.h b/arch/sh/include/asm/thread_info.h
index d570ac2e5cb9..5123bcaa8509 100644
--- a/arch/sh/include/asm/thread_info.h
+++ b/arch/sh/include/asm/thread_info.h
@@ -97,7 +97,7 @@ static inline struct thread_info *current_thread_info(void)
 
 extern struct thread_info *alloc_thread_info(struct task_struct *tsk);
 extern void free_thread_info(struct thread_info *ti);
- 
+
 #endif /* THREAD_SHIFT < PAGE_SHIFT */
 
 #endif /* __ASSEMBLY__ */
@@ -116,6 +116,7 @@ extern void free_thread_info(struct thread_info *ti);
 #define TIF_SYSCALL_AUDIT	5	/* syscall auditing active */
 #define TIF_SECCOMP		6	/* secure computing */
 #define TIF_NOTIFY_RESUME	7	/* callback before returning to user */
+#define TIF_SYSCALL_FTRACE	8	/* for ftrace syscall instrumentation */
 #define TIF_USEDFPU		16	/* FPU was used by this task this quantum (SMP) */
 #define TIF_POLLING_NRFLAG	17	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		18
@@ -129,25 +130,27 @@ extern void free_thread_info(struct thread_info *ti);
 #define _TIF_SYSCALL_AUDIT	(1 << TIF_SYSCALL_AUDIT)
 #define _TIF_SECCOMP		(1 << TIF_SECCOMP)
 #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
+#define _TIF_SYSCALL_FTRACE	(1 << TIF_SYSCALL_FTRACE)
 #define _TIF_USEDFPU		(1 << TIF_USEDFPU)
 #define _TIF_POLLING_NRFLAG	(1 << TIF_POLLING_NRFLAG)
 #define _TIF_FREEZE		(1 << TIF_FREEZE)
 
 /*
- * _TIF_ALLWORK_MASK and _TIF_WORK_MASK need to fit within a byte, or we
+ * _TIF_ALLWORK_MASK and _TIF_WORK_MASK need to fit within 2 bytes, or we
  * blow the tst immediate size constraints and need to fix up
  * arch/sh/kernel/entry-common.S.
  */
 
 /* work to do in syscall trace */
 #define _TIF_WORK_SYSCALL_MASK	(_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP | \
-				 _TIF_SYSCALL_AUDIT | _TIF_SECCOMP)
+				 _TIF_SYSCALL_AUDIT | _TIF_SECCOMP    | \
+				 _TIF_SYSCALL_FTRACE)
 
 /* work to do on any return to u-space */
 #define _TIF_ALLWORK_MASK	(_TIF_SYSCALL_TRACE | _TIF_SIGPENDING      | \
 				 _TIF_NEED_RESCHED  | _TIF_SYSCALL_AUDIT   | \
 				 _TIF_SINGLESTEP    | _TIF_RESTORE_SIGMASK | \
-				 _TIF_NOTIFY_RESUME)
+				 _TIF_NOTIFY_RESUME | _TIF_SYSCALL_FTRACE)
 
 /* work to do on interrupt/exception return */
 #define _TIF_WORK_MASK		(_TIF_ALLWORK_MASK & ~(_TIF_SYSCALL_TRACE | \
diff --git a/arch/sh/include/asm/unwinder.h b/arch/sh/include/asm/unwinder.h
new file mode 100644
index 000000000000..3dc551453e28
--- /dev/null
+++ b/arch/sh/include/asm/unwinder.h
@@ -0,0 +1,25 @@
+#ifndef _LINUX_UNWINDER_H
+#define _LINUX_UNWINDER_H
+
+#include <asm/stacktrace.h>
+
+struct unwinder {
+	const char *name;
+	struct list_head list;
+	int rating;
+	void (*dump)(struct task_struct *, struct pt_regs *,
+		     unsigned long *, const struct stacktrace_ops *, void *);
+};
+
+extern int unwinder_init(void);
+extern int unwinder_register(struct unwinder *);
+
+extern void unwind_stack(struct task_struct *, struct pt_regs *,
+			 unsigned long *, const struct stacktrace_ops *,
+			 void *);
+
+extern void stack_reader_dump(struct task_struct *, struct pt_regs *,
+			      unsigned long *, const struct stacktrace_ops *,
+			      void *);
+
+#endif /* _LINUX_UNWINDER_H */
diff --git a/arch/sh/include/asm/vmlinux.lds.h b/arch/sh/include/asm/vmlinux.lds.h
new file mode 100644
index 000000000000..244ec4ad9a79
--- /dev/null
+++ b/arch/sh/include/asm/vmlinux.lds.h
@@ -0,0 +1,17 @@
+#ifndef __ASM_SH_VMLINUX_LDS_H
+#define __ASM_SH_VMLINUX_LDS_H
+
+#include <asm-generic/vmlinux.lds.h>
+
+#ifdef CONFIG_DWARF_UNWINDER
+#define DWARF_EH_FRAME							\
+	.eh_frame : AT(ADDR(.eh_frame) - LOAD_OFFSET) {			\
+		  VMLINUX_SYMBOL(__start_eh_frame) = .;			\
+		  *(.eh_frame)						\
+		  VMLINUX_SYMBOL(__stop_eh_frame) = .;			\
+	}
+#else
+#define DWARF_EH_FRAME
+#endif
+
+#endif /* __ASM_SH_VMLINUX_LDS_H */
diff --git a/arch/sh/include/cpu-sh4/cpu/dma-sh4a.h b/arch/sh/include/cpu-sh4/cpu/dma-sh4a.h
index 0ed5178fed69..f0886bc880e0 100644
--- a/arch/sh/include/cpu-sh4/cpu/dma-sh4a.h
+++ b/arch/sh/include/cpu-sh4/cpu/dma-sh4a.h
@@ -16,7 +16,8 @@
 #define DMAE0_IRQ	38
 #define SH_DMAC_BASE0	0xFF608020
 #define SH_DMARS_BASE	0xFF609000
-#elif defined(CONFIG_CPU_SUBTYPE_SH7723)
+#elif defined(CONFIG_CPU_SUBTYPE_SH7723) || \
+      defined(CONFIG_CPU_SUBTYPE_SH7724)
 #define DMTE0_IRQ	48	/* DMAC0A*/
 #define DMTE4_IRQ	40	/* DMAC0B */
 #define DMTE6_IRQ	42
diff --git a/arch/sh/include/cpu-sh4/cpu/sh7722.h b/arch/sh/include/cpu-sh4/cpu/sh7722.h
index 738ea43c5038..48560407cbe1 100644
--- a/arch/sh/include/cpu-sh4/cpu/sh7722.h
+++ b/arch/sh/include/cpu-sh4/cpu/sh7722.h
@@ -221,4 +221,18 @@ enum {
 	GPIO_FN_KEYOUT3, GPIO_FN_KEYOUT4_IN6, GPIO_FN_KEYOUT5_IN5,
 };
 
+enum {
+	HWBLK_UNKNOWN = 0,
+	HWBLK_TLB, HWBLK_IC, HWBLK_OC, HWBLK_URAM, HWBLK_XYMEM,
+	HWBLK_INTC, HWBLK_DMAC, HWBLK_SHYWAY, HWBLK_HUDI,
+	HWBLK_UBC, HWBLK_TMU, HWBLK_CMT, HWBLK_RWDT, HWBLK_FLCTL,
+	HWBLK_SCIF0, HWBLK_SCIF1, HWBLK_SCIF2, HWBLK_SIO,
+	HWBLK_SIOF0, HWBLK_SIOF1, HWBLK_IIC, HWBLK_RTC,
+	HWBLK_TPU, HWBLK_IRDA, HWBLK_SDHI, HWBLK_SIM, HWBLK_KEYSC,
+	HWBLK_TSIF, HWBLK_USBF, HWBLK_2DG, HWBLK_SIU, HWBLK_VOU,
+	HWBLK_JPU, HWBLK_BEU, HWBLK_CEU, HWBLK_VEU, HWBLK_VPU,
+	HWBLK_LCDC,
+	HWBLK_NR,
+};
+
 #endif /* __ASM_SH7722_H__ */
diff --git a/arch/sh/include/cpu-sh4/cpu/sh7723.h b/arch/sh/include/cpu-sh4/cpu/sh7723.h
index 14c8ca936781..9b36fae72324 100644
--- a/arch/sh/include/cpu-sh4/cpu/sh7723.h
+++ b/arch/sh/include/cpu-sh4/cpu/sh7723.h
@@ -265,4 +265,21 @@ enum {
 	GPIO_FN_IDEA1, GPIO_FN_IDEA0,
 };
 
+enum {
+	HWBLK_UNKNOWN = 0,
+	HWBLK_TLB, HWBLK_IC, HWBLK_OC, HWBLK_L2C, HWBLK_ILMEM, HWBLK_FPU,
+	HWBLK_INTC, HWBLK_DMAC0, HWBLK_SHYWAY,
+	HWBLK_HUDI, HWBLK_DBG, HWBLK_UBC, HWBLK_SUBC,
+	HWBLK_TMU0, HWBLK_CMT, HWBLK_RWDT, HWBLK_DMAC1, HWBLK_TMU1,
+	HWBLK_FLCTL,
+	HWBLK_SCIF0, HWBLK_SCIF1, HWBLK_SCIF2,
+	HWBLK_SCIF3, HWBLK_SCIF4, HWBLK_SCIF5,
+	HWBLK_MSIOF0, HWBLK_MSIOF1, HWBLK_MERAM, HWBLK_IIC, HWBLK_RTC,
+	HWBLK_ATAPI, HWBLK_ADC, HWBLK_TPU, HWBLK_IRDA, HWBLK_TSIF, HWBLK_ICB,
+	HWBLK_SDHI0, HWBLK_SDHI1, HWBLK_KEYSC, HWBLK_USB,
+	HWBLK_2DG, HWBLK_SIU, HWBLK_VEU2H1, HWBLK_VOU, HWBLK_BEU, HWBLK_CEU,
+	HWBLK_VEU2H0, HWBLK_VPU, HWBLK_LCDC,
+	HWBLK_NR,
+};
+
 #endif /* __ASM_SH7723_H__ */
diff --git a/arch/sh/include/cpu-sh4/cpu/sh7724.h b/arch/sh/include/cpu-sh4/cpu/sh7724.h
index 66fd1184359e..0cd1f71a1116 100644
--- a/arch/sh/include/cpu-sh4/cpu/sh7724.h
+++ b/arch/sh/include/cpu-sh4/cpu/sh7724.h
@@ -266,4 +266,21 @@ enum {
 	GPIO_FN_INTC_IRQ1, GPIO_FN_INTC_IRQ0,
 };
 
+enum {
+	HWBLK_UNKNOWN = 0,
+	HWBLK_TLB, HWBLK_IC, HWBLK_OC, HWBLK_RSMEM, HWBLK_ILMEM, HWBLK_L2C,
+	HWBLK_FPU, HWBLK_INTC, HWBLK_DMAC0, HWBLK_SHYWAY,
+	HWBLK_HUDI, HWBLK_DBG, HWBLK_UBC,
+	HWBLK_TMU0, HWBLK_CMT, HWBLK_RWDT, HWBLK_DMAC1, HWBLK_TMU1,
+	HWBLK_SCIF0, HWBLK_SCIF1, HWBLK_SCIF2, HWBLK_SCIF3,
+	HWBLK_SCIF4, HWBLK_SCIF5, HWBLK_MSIOF0, HWBLK_MSIOF1,
+	HWBLK_KEYSC, HWBLK_RTC, HWBLK_IIC0, HWBLK_IIC1,
+	HWBLK_MMC, HWBLK_ETHER, HWBLK_ATAPI, HWBLK_TPU, HWBLK_IRDA,
+	HWBLK_TSIF, HWBLK_USB1, HWBLK_USB0, HWBLK_2DG,
+	HWBLK_SDHI0, HWBLK_SDHI1, HWBLK_VEU1, HWBLK_CEU1, HWBLK_BEU1,
+	HWBLK_2DDMAC, HWBLK_SPU, HWBLK_JPU, HWBLK_VOU,
+	HWBLK_BEU0, HWBLK_CEU0,	HWBLK_VEU0, HWBLK_VPU, HWBLK_LCDC,
+	HWBLK_NR,
+};
+
 #endif /* __ASM_SH7724_H__ */
diff --git a/arch/sh/include/mach-common/mach/migor.h b/arch/sh/include/mach-common/mach/migor.h
deleted file mode 100644
index e451f0229e00..000000000000
--- a/arch/sh/include/mach-common/mach/migor.h
+++ /dev/null
@@ -1,64 +0,0 @@
-#ifndef __ASM_SH_MIGOR_H
-#define __ASM_SH_MIGOR_H
-
-/*
- * linux/include/asm-sh/migor.h
- *
- * Copyright (C) 2008 Renesas Solutions
- *
- * Portions Copyright (C) 2007 Nobuhiro Iwamatsu
- *
- * 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 <asm/addrspace.h>
-
-/* GPIO */
-#define PORT_PACR 0xa4050100
-#define PORT_PDCR 0xa4050106
-#define PORT_PECR 0xa4050108
-#define PORT_PHCR 0xa405010e
-#define PORT_PJCR 0xa4050110
-#define PORT_PKCR 0xa4050112
-#define PORT_PLCR 0xa4050114
-#define PORT_PMCR 0xa4050116
-#define PORT_PRCR 0xa405011c
-#define PORT_PTCR 0xa4050140
-#define PORT_PUCR 0xa4050142
-#define PORT_PVCR 0xa4050144
-#define PORT_PWCR 0xa4050146
-#define PORT_PXCR 0xa4050148
-#define PORT_PYCR 0xa405014a
-#define PORT_PZCR 0xa405014c
-#define PORT_PADR 0xa4050120
-#define PORT_PHDR 0xa405012e
-#define PORT_PTDR 0xa4050160
-#define PORT_PWDR 0xa4050166
-
-#define PORT_HIZCRA 0xa4050158
-#define PORT_HIZCRC 0xa405015c
-
-#define PORT_MSELCRB 0xa4050182
-
-#define PORT_PSELA 0xa405014e
-#define PORT_PSELB 0xa4050150
-#define PORT_PSELC 0xa4050152
-#define PORT_PSELD 0xa4050154
-#define PORT_PSELE 0xa4050156
-
-#define PORT_HIZCRA 0xa4050158
-#define PORT_HIZCRB 0xa405015a
-#define PORT_HIZCRC 0xa405015c
-
-#define BSC_CS4BCR 0xfec10010
-#define BSC_CS6ABCR 0xfec1001c
-#define BSC_CS4WCR 0xfec10030
-
-#include <video/sh_mobile_lcdc.h>
-
-int migor_lcd_qvga_setup(void *board_data, void *sys_ops_handle,
-			 struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
-
-#endif /* __ASM_SH_MIGOR_H */
diff --git a/arch/sh/include/mach-common/mach/romimage.h b/arch/sh/include/mach-common/mach/romimage.h
new file mode 100644
index 000000000000..267e24112d82
--- /dev/null
+++ b/arch/sh/include/mach-common/mach/romimage.h
@@ -0,0 +1 @@
+/* do nothing here by default */
diff --git a/arch/sh/include/mach-kfr2r09/mach/kfr2r09.h b/arch/sh/include/mach-kfr2r09/mach/kfr2r09.h
new file mode 100644
index 000000000000..174374e19547
--- /dev/null
+++ b/arch/sh/include/mach-kfr2r09/mach/kfr2r09.h
@@ -0,0 +1,21 @@
+#ifndef __ASM_SH_KFR2R09_H
+#define __ASM_SH_KFR2R09_H
+
+#include <video/sh_mobile_lcdc.h>
+
+#ifdef CONFIG_FB_SH_MOBILE_LCDC
+void kfr2r09_lcd_on(void *board_data);
+void kfr2r09_lcd_off(void *board_data);
+int kfr2r09_lcd_setup(void *board_data, void *sys_ops_handle,
+		      struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
+#else
+static inline void kfr2r09_lcd_on(void *board_data) {}
+static inline void kfr2r09_lcd_off(void *board_data) {}
+static inline int kfr2r09_lcd_setup(void *board_data, void *sys_ops_handle,
+				    struct sh_mobile_lcdc_sys_bus_ops *sys_ops)
+{
+	return -ENODEV;
+}
+#endif
+
+#endif /* __ASM_SH_KFR2R09_H */
diff --git a/arch/sh/include/mach-kfr2r09/mach/partner-jet-setup.txt b/arch/sh/include/mach-kfr2r09/mach/partner-jet-setup.txt
new file mode 100644
index 000000000000..9c85088728a7
--- /dev/null
+++ b/arch/sh/include/mach-kfr2r09/mach/partner-jet-setup.txt
@@ -0,0 +1,134 @@
+LIST "partner-jet-setup.txt - 20090729 Magnus Damm"
+LIST "set up enough of the kfr2r09 hardware to boot the kernel"
+
+LIST "zImage (RAM boot)"
+LIST "This script can be used to boot the kernel from RAM via JTAG:"
+LIST "> < partner-jet-setup.txt"
+LIST "> RD zImage, 0xa8800000"
+LIST "> G=0xa8800000"
+
+LIST "romImage (Flash boot)"
+LIST "Use the following command to burn the zImage to flash via JTAG:"
+LIST "> RD romImage, 0"
+
+LIST "--------------------------------"
+
+LIST "disable watchdog"
+EW 0xa4520004, 0xa507
+
+LIST "select mode for cs5 + cs6"
+ED 0xff800020, 0xa5a50001
+ED 0xfec10000, 0x0000001b
+
+LIST "setup clocks"
+ED 0xa4150004, 0x00000050
+ED 0xa4150000, 0x91053508
+WAIT 1
+ED 0xa4150024, 0x00005000
+
+LIST "setup pins"
+EB 0xa4050120, 0x00
+EB 0xa4050122, 0x00
+EB 0xa4050124, 0x00
+EB 0xa4050126, 0x00
+EB 0xa4050128, 0xA0
+EB 0xa405012A, 0x10
+EB 0xa405012C, 0x00
+EB 0xa405012E, 0x00
+EB 0xa4050130, 0x00
+EB 0xa4050132, 0x00
+EB 0xa4050134, 0x01
+EB 0xa4050136, 0x40
+EB 0xa4050138, 0x00
+EB 0xa405013A, 0x00
+EB 0xa405013C, 0x00
+EB 0xa405013E, 0x20
+EB 0xa4050160, 0x00
+EB 0xa4050162, 0x40
+EB 0xa4050164, 0x03
+EB 0xa4050166, 0x00
+EB 0xa4050168, 0x00
+EB 0xa405016A, 0x00
+EB 0xa405016C, 0x00
+
+EW 0xa405014E, 0x5660
+EW 0xa4050150, 0x0145
+EW 0xa4050152, 0x1550
+EW 0xa4050154, 0x0200
+EW 0xa4050156, 0x0040
+
+EW 0xa4050158, 0x0000
+EW 0xa405015a, 0x0000
+EW 0xa405015c, 0x0000
+EW 0xa405015e, 0x0000
+
+EW 0xa4050180, 0x0000
+EW 0xa4050182, 0x8002
+EW 0xa4050184, 0x0000
+
+EW 0xa405018a, 0x9991
+EW 0xa405018c, 0x8011
+EW 0xa405018e, 0x9550
+
+EW 0xa4050100, 0x0000
+EW 0xa4050102, 0x5540
+EW 0xa4050104, 0x0000
+EW 0xa4050106, 0x0000
+EW 0xa4050108, 0x4550
+EW 0xa405010a, 0x0130
+EW 0xa405010c, 0x0555
+EW 0xa405010e, 0x0000
+EW 0xa4050110, 0x0000
+EW 0xa4050112, 0xAAA8
+EW 0xa4050114, 0x8305
+EW 0xa4050116, 0x10F0
+EW 0xa4050118, 0x0F50
+EW 0xa405011a, 0x0000
+EW 0xa405011c, 0x0000
+EW 0xa405011e, 0x0555
+EW 0xa4050140, 0x0000
+EW 0xa4050142, 0x5141
+EW 0xa4050144, 0x5005
+EW 0xa4050146, 0xAAA9
+EW 0xa4050148, 0xFAA9
+EW 0xa405014a, 0x3000
+EW 0xa405014c, 0x0000
+
+LIST "setup sdram"
+ED 0xFD000108, 0x40000301
+ED 0xFD000020, 0x011B0002
+ED 0xFD000030, 0x03060E02
+ED 0xFD000034, 0x01020102
+ED 0xFD000038, 0x01090406
+ED 0xFD000008, 0x00000004
+ED 0xFD000040, 0x00000001
+ED 0xFD000040, 0x00000000
+ED 0xFD000018, 0x00000001
+
+WAIT 1
+
+ED 0xFD000014, 0x00000002
+ED 0xFD000060, 0x00000032
+ED 0xFD000060, 0x00020000
+ED 0xFD000014, 0x00000004
+ED 0xFD000014, 0x00000004
+ED 0xFD000010, 0x00000001
+ED 0xFD000044, 0x000004AF
+ED 0xFD000048, 0x20CF0037
+
+LIST "read 16 bytes from sdram"
+DD 0xa8000000, 0xa8000000, 1
+DD 0xa8000004, 0xa8000004, 1
+DD 0xa8000008, 0xa8000008, 1
+DD 0xa800000c, 0xa800000c, 1
+
+ED 0xFD000014, 0x00000002
+ED 0xFD000014, 0x00000004
+ED 0xFD000108, 0x40000300
+ED 0xFD000040, 0x00010000
+
+LIST "write to internal ram"
+ED 0xfd8007fc, 0
+
+LIST "setup cache"
+ED 0xff00001c, 0x0000090b
diff --git a/arch/sh/include/mach-kfr2r09/mach/romimage.h b/arch/sh/include/mach-kfr2r09/mach/romimage.h
new file mode 100644
index 000000000000..f5aa8e16770c
--- /dev/null
+++ b/arch/sh/include/mach-kfr2r09/mach/romimage.h
@@ -0,0 +1,75 @@
+/* kfr2r09 board specific boot code:
+ * converts the "partner-jet-script.txt" script into assembly
+ * the assembly code is the first code to be executed in the romImage
+ */
+
+/* The LIST command is used to include comments in the script */
+.macro	LIST comment
+.endm
+
+/* The ED command is used to write a 32-bit word */
+.macro  ED, addr, data
+        mov.l 1f ,r1
+        mov.l 2f ,r0
+        mov.l r0, @r1
+	bra 3f
+	 nop
+	.align 2
+1:	.long \addr
+2:	.long \data
+3:
+.endm
+
+/* The EW command is used to write a 16-bit word */
+.macro  EW, addr, data
+        mov.l 1f ,r1
+        mov.l 2f ,r0
+        mov.w r0, @r1
+	bra 3f
+	 nop
+	.align 2
+1:	.long \addr
+2:	.long \data
+3:
+.endm
+
+/* The EB command is used to write an 8-bit word */
+.macro  EB, addr, data
+        mov.l 1f ,r1
+        mov.l 2f ,r0
+        mov.b r0, @r1
+	bra 3f
+	 nop
+	.align 2
+1:	.long \addr
+2:	.long \data
+3:
+.endm
+
+/* The WAIT command is used to delay the execution */
+.macro  WAIT, time
+        mov.l  2f ,r3
+1:
+        nop
+        tst     r3, r3
+        bf/s    1b
+         dt      r3
+	bra	3f
+	 nop
+	.align 2
+2:	.long \time * 100
+3:
+.endm
+
+/* The DD command is used to read a 32-bit word */
+.macro  DD, addr, addr2, nr
+        mov.l 1f ,r1
+        mov.l @r1, r0
+	bra 2f
+	 nop
+	.align 2
+1:	.long \addr
+2:
+.endm
+
+#include "partner-jet-setup.txt"
diff --git a/arch/sh/include/mach-migor/mach/migor.h b/arch/sh/include/mach-migor/mach/migor.h
new file mode 100644
index 000000000000..cee6cb88e020
--- /dev/null
+++ b/arch/sh/include/mach-migor/mach/migor.h
@@ -0,0 +1,14 @@
+#ifndef __ASM_SH_MIGOR_H
+#define __ASM_SH_MIGOR_H
+
+#define PORT_MSELCRB 0xa4050182
+#define BSC_CS4BCR 0xfec10010
+#define BSC_CS6ABCR 0xfec1001c
+#define BSC_CS4WCR 0xfec10030
+
+#include <video/sh_mobile_lcdc.h>
+
+int migor_lcd_qvga_setup(void *board_data, void *sys_ops_handle,
+			 struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
+
+#endif /* __ASM_SH_MIGOR_H */
diff --git a/arch/sh/kernel/Makefile_32 b/arch/sh/kernel/Makefile_32
index 9411e3e31e68..f2245ebf0b31 100644
--- a/arch/sh/kernel/Makefile_32
+++ b/arch/sh/kernel/Makefile_32
@@ -9,10 +9,10 @@ ifdef CONFIG_FUNCTION_TRACER
 CFLAGS_REMOVE_ftrace.o = -pg
 endif
 
-obj-y	:= debugtraps.o idle.o io.o io_generic.o irq.o			\
+obj-y	:= debugtraps.o dumpstack.o idle.o io.o io_generic.o irq.o	\
 	   machvec.o process_32.o ptrace_32.o setup.o signal_32.o	\
-	   sys_sh.o sys_sh32.o syscalls_32.o time.o topology.o	\
-	   traps.o traps_32.o
+	   sys_sh.o sys_sh32.o syscalls_32.o time.o topology.o		\
+	   traps.o traps_32.o unwinder.o
 
 obj-y				+= cpu/
 obj-$(CONFIG_VSYSCALL)		+= vsyscall/
@@ -29,8 +29,11 @@ obj-$(CONFIG_IO_TRAPPED)	+= io_trapped.o
 obj-$(CONFIG_KPROBES)		+= kprobes.o
 obj-$(CONFIG_GENERIC_GPIO)	+= gpio.o
 obj-$(CONFIG_DYNAMIC_FTRACE)	+= ftrace.o
+obj-$(CONFIG_FTRACE_SYSCALLS)	+= ftrace.o
+obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
 obj-$(CONFIG_DUMP_CODE)		+= disassemble.o
 obj-$(CONFIG_HIBERNATION)	+= swsusp.o
+obj-$(CONFIG_DWARF_UNWINDER)	+= dwarf.o
 
 obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)	+= localtimer.o
 
diff --git a/arch/sh/kernel/Makefile_64 b/arch/sh/kernel/Makefile_64
index 67b9f6c6326b..639ee514266c 100644
--- a/arch/sh/kernel/Makefile_64
+++ b/arch/sh/kernel/Makefile_64
@@ -2,7 +2,7 @@ extra-y	:= head_64.o init_task.o vmlinux.lds
 
 obj-y	:= debugtraps.o idle.o io.o io_generic.o irq.o machvec.o process_64.o \
 	   ptrace_64.o setup.o signal_64.o sys_sh.o sys_sh64.o \
-	   syscalls_64.o time.o topology.o traps.o traps_64.o
+	   syscalls_64.o time.o topology.o traps.o traps_64.o unwinder.o
 
 obj-y				+= cpu/
 obj-$(CONFIG_SMP)		+= smp.o
@@ -13,6 +13,7 @@ obj-$(CONFIG_CRASH_DUMP)	+= crash_dump.o
 obj-$(CONFIG_STACKTRACE)	+= stacktrace.o
 obj-$(CONFIG_IO_TRAPPED)	+= io_trapped.o
 obj-$(CONFIG_GENERIC_GPIO)	+= gpio.o
+obj-$(CONFIG_DWARF_UNWINDER)	+= dwarf.o
 
 obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)	+= localtimer.o
 
diff --git a/arch/sh/kernel/asm-offsets.c b/arch/sh/kernel/asm-offsets.c
index 99aceb28ee24..d218e808294e 100644
--- a/arch/sh/kernel/asm-offsets.c
+++ b/arch/sh/kernel/asm-offsets.c
@@ -26,6 +26,7 @@ int main(void)
 	DEFINE(TI_CPU,		offsetof(struct thread_info, cpu));
 	DEFINE(TI_PRE_COUNT,	offsetof(struct thread_info, preempt_count));
 	DEFINE(TI_RESTART_BLOCK,offsetof(struct thread_info, restart_block));
+	DEFINE(TI_SIZE,		sizeof(struct thread_info));
 
 #ifdef CONFIG_HIBERNATION
 	DEFINE(PBE_ADDRESS, offsetof(struct pbe, address));
diff --git a/arch/sh/kernel/cpu/Makefile b/arch/sh/kernel/cpu/Makefile
index eecad7cbd61e..3d6b9312dc47 100644
--- a/arch/sh/kernel/cpu/Makefile
+++ b/arch/sh/kernel/cpu/Makefile
@@ -19,4 +19,4 @@ obj-$(CONFIG_UBC_WAKEUP)	+= ubc.o
 obj-$(CONFIG_SH_ADC)		+= adc.o
 obj-$(CONFIG_SH_CLK_CPG)	+= clock-cpg.o
 
-obj-y	+= irq/ init.o clock.o
+obj-y	+= irq/ init.o clock.o hwblk.o
diff --git a/arch/sh/kernel/cpu/hwblk.c b/arch/sh/kernel/cpu/hwblk.c
new file mode 100644
index 000000000000..c0ad7d46e784
--- /dev/null
+++ b/arch/sh/kernel/cpu/hwblk.c
@@ -0,0 +1,155 @@
+#include <linux/clk.h>
+#include <linux/compiler.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include <asm/suspend.h>
+#include <asm/hwblk.h>
+#include <asm/clock.h>
+
+static DEFINE_SPINLOCK(hwblk_lock);
+
+static void hwblk_area_mod_cnt(struct hwblk_info *info,
+			       int area, int counter, int value, int goal)
+{
+	struct hwblk_area *hap = info->areas + area;
+
+	hap->cnt[counter] += value;
+
+	if (hap->cnt[counter] != goal)
+		return;
+
+	if (hap->flags & HWBLK_AREA_FLAG_PARENT)
+		hwblk_area_mod_cnt(info, hap->parent, counter, value, goal);
+}
+
+
+static int __hwblk_mod_cnt(struct hwblk_info *info, int hwblk,
+			  int counter, int value, int goal)
+{
+	struct hwblk *hp = info->hwblks + hwblk;
+
+	hp->cnt[counter] += value;
+	if (hp->cnt[counter] == goal)
+		hwblk_area_mod_cnt(info, hp->area, counter, value, goal);
+
+	return hp->cnt[counter];
+}
+
+static void hwblk_mod_cnt(struct hwblk_info *info, int hwblk,
+			  int counter, int value, int goal)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&hwblk_lock, flags);
+	__hwblk_mod_cnt(info, hwblk, counter, value, goal);
+	spin_unlock_irqrestore(&hwblk_lock, flags);
+}
+
+void hwblk_cnt_inc(struct hwblk_info *info, int hwblk, int counter)
+{
+	hwblk_mod_cnt(info, hwblk, counter, 1, 1);
+}
+
+void hwblk_cnt_dec(struct hwblk_info *info, int hwblk, int counter)
+{
+	hwblk_mod_cnt(info, hwblk, counter, -1, 0);
+}
+
+void hwblk_enable(struct hwblk_info *info, int hwblk)
+{
+	struct hwblk *hp = info->hwblks + hwblk;
+	unsigned long tmp;
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&hwblk_lock, flags);
+
+	ret = __hwblk_mod_cnt(info, hwblk, HWBLK_CNT_USAGE, 1, 1);
+	if (ret == 1) {
+		tmp = __raw_readl(hp->mstp);
+		tmp &= ~(1 << hp->bit);
+		__raw_writel(tmp, hp->mstp);
+	}
+
+	spin_unlock_irqrestore(&hwblk_lock, flags);
+}
+
+void hwblk_disable(struct hwblk_info *info, int hwblk)
+{
+	struct hwblk *hp = info->hwblks + hwblk;
+	unsigned long tmp;
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&hwblk_lock, flags);
+
+	ret = __hwblk_mod_cnt(info, hwblk, HWBLK_CNT_USAGE, -1, 0);
+	if (ret == 0) {
+		tmp = __raw_readl(hp->mstp);
+		tmp |= 1 << hp->bit;
+		__raw_writel(tmp, hp->mstp);
+	}
+
+	spin_unlock_irqrestore(&hwblk_lock, flags);
+}
+
+struct hwblk_info *hwblk_info;
+
+int __init hwblk_register(struct hwblk_info *info)
+{
+	hwblk_info = info;
+	return 0;
+}
+
+int __init __weak arch_hwblk_init(void)
+{
+	return 0;
+}
+
+int __weak arch_hwblk_sleep_mode(void)
+{
+	return SUSP_SH_SLEEP;
+}
+
+int __init hwblk_init(void)
+{
+	return arch_hwblk_init();
+}
+
+/* allow clocks to enable and disable hardware blocks */
+static int sh_hwblk_clk_enable(struct clk *clk)
+{
+	if (!hwblk_info)
+		return -ENOENT;
+
+	hwblk_enable(hwblk_info, clk->arch_flags);
+	return 0;
+}
+
+static void sh_hwblk_clk_disable(struct clk *clk)
+{
+	if (hwblk_info)
+		hwblk_disable(hwblk_info, clk->arch_flags);
+}
+
+static struct clk_ops sh_hwblk_clk_ops = {
+	.enable		= sh_hwblk_clk_enable,
+	.disable	= sh_hwblk_clk_disable,
+	.recalc		= followparent_recalc,
+};
+
+int __init sh_hwblk_clk_register(struct clk *clks, int nr)
+{
+	struct clk *clkp;
+	int ret = 0;
+	int k;
+
+	for (k = 0; !ret && (k < nr); k++) {
+		clkp = clks + k;
+		clkp->ops = &sh_hwblk_clk_ops;
+		ret |= clk_register(clkp);
+	}
+
+	return ret;
+}
diff --git a/arch/sh/kernel/cpu/init.c b/arch/sh/kernel/cpu/init.c
index ad85421099cd..d40b9db5be03 100644
--- a/arch/sh/kernel/cpu/init.c
+++ b/arch/sh/kernel/cpu/init.c
@@ -3,7 +3,7 @@
  *
  * CPU init code
  *
- * Copyright (C) 2002 - 2007  Paul Mundt
+ * Copyright (C) 2002 - 2009  Paul Mundt
  * Copyright (C) 2003  Richard Curnow
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -62,6 +62,37 @@ static void __init speculative_execution_init(void)
 #define speculative_execution_init()	do { } while (0)
 #endif
 
+#ifdef CONFIG_CPU_SH4A
+#define EXPMASK			0xff2f0004
+#define EXPMASK_RTEDS		(1 << 0)
+#define EXPMASK_BRDSSLP		(1 << 1)
+#define EXPMASK_MMCAW		(1 << 4)
+
+static void __init expmask_init(void)
+{
+	unsigned long expmask = __raw_readl(EXPMASK);
+
+	/*
+	 * Future proofing.
+	 *
+	 * Disable support for slottable sleep instruction
+	 * and non-nop instructions in the rte delay slot.
+	 */
+	expmask &= ~(EXPMASK_RTEDS | EXPMASK_BRDSSLP);
+
+	/*
+	 * Enable associative writes to the memory-mapped cache array
+	 * until the cache flush ops have been rewritten.
+	 */
+	expmask |= EXPMASK_MMCAW;
+
+	__raw_writel(expmask, EXPMASK);
+	ctrl_barrier();
+}
+#else
+#define expmask_init()	do { } while (0)
+#endif
+
 /* 2nd-level cache init */
 void __uses_jump_to_uncached __attribute__ ((weak)) l2_cache_init(void)
 {
@@ -321,4 +352,5 @@ asmlinkage void __init sh_cpu_init(void)
 #endif
 
 	speculative_execution_init();
+	expmask_init();
 }
diff --git a/arch/sh/kernel/cpu/sh2/entry.S b/arch/sh/kernel/cpu/sh2/entry.S
index becc54c45692..c8a4331d9b8d 100644
--- a/arch/sh/kernel/cpu/sh2/entry.S
+++ b/arch/sh/kernel/cpu/sh2/entry.S
@@ -227,8 +227,9 @@ ENTRY(sh_bios_handler)
 	mov.l	@r15+, r14
 	add	#8,r15
 	lds.l	@r15+, pr
+	mov.l	@r15+,r15
 	rte
-	 mov.l	@r15+,r15
+	 nop
 	.align	2
 1:	.long	gdb_vbr_vector
 #endif /* CONFIG_SH_STANDARD_BIOS */
diff --git a/arch/sh/kernel/cpu/sh2a/entry.S b/arch/sh/kernel/cpu/sh2a/entry.S
index ab3903eeda5c..222742ddc0d6 100644
--- a/arch/sh/kernel/cpu/sh2a/entry.S
+++ b/arch/sh/kernel/cpu/sh2a/entry.S
@@ -176,8 +176,9 @@ ENTRY(sh_bios_handler)
 	movml.l	@r15+,r14
 	add	#8,r15
 	lds.l	@r15+, pr
+	mov.l	@r15+,r15
 	rte
-	 mov.l	@r15+,r15
+	 nop
 	.align	2
 1:	.long	gdb_vbr_vector
 #endif /* CONFIG_SH_STANDARD_BIOS */
diff --git a/arch/sh/kernel/cpu/sh3/entry.S b/arch/sh/kernel/cpu/sh3/entry.S
index 3cb531f233f2..67ad6467c694 100644
--- a/arch/sh/kernel/cpu/sh3/entry.S
+++ b/arch/sh/kernel/cpu/sh3/entry.S
@@ -137,6 +137,7 @@ ENTRY(tlb_protection_violation_store)
 	 mov	#1, r5
 
 call_dpf:
+	setup_frame_reg
 	mov.l	1f, r0
 	mov	r5, r8
 	mov.l	@r0, r6
diff --git a/arch/sh/kernel/cpu/sh4a/Makefile b/arch/sh/kernel/cpu/sh4a/Makefile
index ebdd391d5f42..12cddf4c721d 100644
--- a/arch/sh/kernel/cpu/sh4a/Makefile
+++ b/arch/sh/kernel/cpu/sh4a/Makefile
@@ -25,9 +25,9 @@ clock-$(CONFIG_CPU_SUBTYPE_SH7780)	:= clock-sh7780.o
 clock-$(CONFIG_CPU_SUBTYPE_SH7785)	:= clock-sh7785.o
 clock-$(CONFIG_CPU_SUBTYPE_SH7786)	:= clock-sh7786.o
 clock-$(CONFIG_CPU_SUBTYPE_SH7343)	:= clock-sh7343.o
-clock-$(CONFIG_CPU_SUBTYPE_SH7722)	:= clock-sh7722.o
-clock-$(CONFIG_CPU_SUBTYPE_SH7723)	:= clock-sh7723.o
-clock-$(CONFIG_CPU_SUBTYPE_SH7724)	:= clock-sh7724.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7722)	:= clock-sh7722.o hwblk-sh7722.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7723)	:= clock-sh7723.o hwblk-sh7723.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7724)	:= clock-sh7724.o hwblk-sh7724.o
 clock-$(CONFIG_CPU_SUBTYPE_SH7366)	:= clock-sh7366.o
 clock-$(CONFIG_CPU_SUBTYPE_SHX3)	:= clock-shx3.o
 
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
index 40f859354f79..5b1bbbe63b1b 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
@@ -22,6 +22,8 @@
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <asm/clock.h>
+#include <asm/hwblk.h>
+#include <cpu/sh7722.h>
 
 /* SH7722 registers */
 #define FRQCR		0xa4150000
@@ -30,9 +32,6 @@
 #define SCLKBCR		0xa415000c
 #define IRDACLKCR	0xa4150018
 #define PLLCR		0xa4150024
-#define MSTPCR0		0xa4150030
-#define MSTPCR1		0xa4150034
-#define MSTPCR2		0xa4150038
 #define DLLFRQ		0xa4150050
 
 /* Fixed 32 KHz root clock for RTC and Power Management purposes */
@@ -140,35 +139,37 @@ struct clk div6_clks[] = {
 	SH_CLK_DIV6("video_clk", &pll_clk, VCLKCR, 0),
 };
 
-#define MSTP(_str, _parent, _reg, _bit, _flags) \
-  SH_CLK_MSTP32(_str, -1, _parent, _reg, _bit, _flags)
+#define R_CLK &r_clk
+#define P_CLK &div4_clks[DIV4_P]
+#define B_CLK &div4_clks[DIV4_B]
+#define U_CLK &div4_clks[DIV4_U]
 
 static struct clk mstp_clks[] = {
-	MSTP("uram0", &div4_clks[DIV4_U], MSTPCR0, 28, CLK_ENABLE_ON_INIT),
-	MSTP("xymem0", &div4_clks[DIV4_B], MSTPCR0, 26, CLK_ENABLE_ON_INIT),
-	MSTP("tmu0", &div4_clks[DIV4_P], MSTPCR0, 15, 0),
-	MSTP("cmt0", &r_clk, MSTPCR0, 14, 0),
-	MSTP("rwdt0", &r_clk, MSTPCR0, 13, 0),
-	MSTP("flctl0", &div4_clks[DIV4_P], MSTPCR0, 10, 0),
-	MSTP("scif0", &div4_clks[DIV4_P], MSTPCR0, 7, 0),
-	MSTP("scif1", &div4_clks[DIV4_P], MSTPCR0, 6, 0),
-	MSTP("scif2", &div4_clks[DIV4_P], MSTPCR0, 5, 0),
+	SH_HWBLK_CLK("uram0", -1, U_CLK, HWBLK_URAM, CLK_ENABLE_ON_INIT),
+	SH_HWBLK_CLK("xymem0", -1, B_CLK, HWBLK_XYMEM, CLK_ENABLE_ON_INIT),
+	SH_HWBLK_CLK("tmu0", -1, P_CLK, HWBLK_TMU, 0),
+	SH_HWBLK_CLK("cmt0", -1, R_CLK, HWBLK_CMT, 0),
+	SH_HWBLK_CLK("rwdt0", -1, R_CLK, HWBLK_RWDT, 0),
+	SH_HWBLK_CLK("flctl0", -1, P_CLK, HWBLK_FLCTL, 0),
+	SH_HWBLK_CLK("scif0", -1, P_CLK, HWBLK_SCIF0, 0),
+	SH_HWBLK_CLK("scif1", -1, P_CLK, HWBLK_SCIF1, 0),
+	SH_HWBLK_CLK("scif2", -1, P_CLK, HWBLK_SCIF2, 0),
 
-	MSTP("i2c0", &div4_clks[DIV4_P], MSTPCR1, 9, 0),
-	MSTP("rtc0", &r_clk, MSTPCR1, 8, 0),
+	SH_HWBLK_CLK("i2c0", -1, P_CLK, HWBLK_IIC, 0),
+	SH_HWBLK_CLK("rtc0", -1, R_CLK, HWBLK_RTC, 0),
 
-	MSTP("sdhi0", &div4_clks[DIV4_P], MSTPCR2, 18, 0),
-	MSTP("keysc0", &r_clk, MSTPCR2, 14, 0),
-	MSTP("usbf0", &div4_clks[DIV4_P], MSTPCR2, 11, 0),
-	MSTP("2dg0", &div4_clks[DIV4_B], MSTPCR2, 9, 0),
-	MSTP("siu0", &div4_clks[DIV4_B], MSTPCR2, 8, 0),
-	MSTP("vou0", &div4_clks[DIV4_B], MSTPCR2, 5, 0),
-	MSTP("jpu0", &div4_clks[DIV4_B], MSTPCR2, 6, CLK_ENABLE_ON_INIT),
-	MSTP("beu0", &div4_clks[DIV4_B], MSTPCR2, 4, 0),
-	MSTP("ceu0", &div4_clks[DIV4_B], MSTPCR2, 3, 0),
-	MSTP("veu0", &div4_clks[DIV4_B], MSTPCR2, 2, CLK_ENABLE_ON_INIT),
-	MSTP("vpu0", &div4_clks[DIV4_B], MSTPCR2, 1, CLK_ENABLE_ON_INIT),
-	MSTP("lcdc0", &div4_clks[DIV4_B], MSTPCR2, 0, 0),
+	SH_HWBLK_CLK("sdhi0", -1, P_CLK, HWBLK_SDHI, 0),
+	SH_HWBLK_CLK("keysc0", -1, R_CLK, HWBLK_KEYSC, 0),
+	SH_HWBLK_CLK("usbf0", -1, P_CLK, HWBLK_USBF, 0),
+	SH_HWBLK_CLK("2dg0", -1, B_CLK, HWBLK_2DG, 0),
+	SH_HWBLK_CLK("siu0", -1, B_CLK, HWBLK_SIU, 0),
+	SH_HWBLK_CLK("vou0", -1, B_CLK, HWBLK_VOU, 0),
+	SH_HWBLK_CLK("jpu0", -1, B_CLK, HWBLK_JPU, CLK_ENABLE_ON_INIT),
+	SH_HWBLK_CLK("beu0", -1, B_CLK, HWBLK_BEU, 0),
+	SH_HWBLK_CLK("ceu0", -1, B_CLK, HWBLK_CEU, 0),
+	SH_HWBLK_CLK("veu0", -1, B_CLK, HWBLK_VEU, CLK_ENABLE_ON_INIT),
+	SH_HWBLK_CLK("vpu0", -1, B_CLK, HWBLK_VPU, CLK_ENABLE_ON_INIT),
+	SH_HWBLK_CLK("lcdc0", -1, P_CLK, HWBLK_LCDC, 0),
 };
 
 int __init arch_clk_init(void)
@@ -191,7 +192,7 @@ int __init arch_clk_init(void)
 		ret = sh_clk_div6_register(div6_clks, ARRAY_SIZE(div6_clks));
 
 	if (!ret)
-		ret = sh_clk_mstp32_register(mstp_clks, ARRAY_SIZE(mstp_clks));
+		ret = sh_hwblk_clk_register(mstp_clks, ARRAY_SIZE(mstp_clks));
 
 	return ret;
 }
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c
index e67c2678b8ae..e5c63911403c 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c
@@ -22,6 +22,8 @@
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <asm/clock.h>
+#include <asm/hwblk.h>
+#include <cpu/sh7723.h>
 
 /* SH7723 registers */
 #define FRQCR		0xa4150000
@@ -30,9 +32,6 @@
 #define SCLKBCR		0xa415000c
 #define IRDACLKCR	0xa4150018
 #define PLLCR		0xa4150024
-#define MSTPCR0		0xa4150030
-#define MSTPCR1		0xa4150034
-#define MSTPCR2		0xa4150038
 #define DLLFRQ		0xa4150050
 
 /* Fixed 32 KHz root clock for RTC and Power Management purposes */
@@ -140,60 +139,64 @@ struct clk div6_clks[] = {
 	SH_CLK_DIV6("video_clk", &pll_clk, VCLKCR, 0),
 };
 
-#define MSTP(_str, _parent, _reg, _bit, _force_on, _need_cpg, _need_ram) \
-  SH_CLK_MSTP32(_str, -1, _parent, _reg, _bit, _force_on * CLK_ENABLE_ON_INIT)
+#define R_CLK (&r_clk)
+#define P_CLK (&div4_clks[DIV4_P])
+#define B_CLK (&div4_clks[DIV4_B])
+#define U_CLK (&div4_clks[DIV4_U])
+#define I_CLK (&div4_clks[DIV4_I])
+#define SH_CLK (&div4_clks[DIV4_SH])
 
 static struct clk mstp_clks[] = {
 	/* See page 60 of Datasheet V1.0: Overview -> Block Diagram */
-	MSTP("tlb0", &div4_clks[DIV4_I], MSTPCR0, 31, 1, 1, 0),
-	MSTP("ic0", &div4_clks[DIV4_I], MSTPCR0, 30, 1, 1, 0),
-	MSTP("oc0", &div4_clks[DIV4_I], MSTPCR0, 29, 1, 1, 0),
-	MSTP("l2c0", &div4_clks[DIV4_SH], MSTPCR0, 28, 1, 1, 0),
-	MSTP("ilmem0", &div4_clks[DIV4_I], MSTPCR0, 27, 1, 1, 0),
-	MSTP("fpu0", &div4_clks[DIV4_I], MSTPCR0, 24, 1, 1, 0),
-	MSTP("intc0", &div4_clks[DIV4_I], MSTPCR0, 22, 1, 1, 0),
-	MSTP("dmac0", &div4_clks[DIV4_B], MSTPCR0, 21, 0, 1, 1),
-	MSTP("sh0", &div4_clks[DIV4_SH], MSTPCR0, 20, 0, 1, 0),
-	MSTP("hudi0", &div4_clks[DIV4_P], MSTPCR0, 19, 0, 1, 0),
-	MSTP("ubc0", &div4_clks[DIV4_I], MSTPCR0, 17, 0, 1, 0),
-	MSTP("tmu0", &div4_clks[DIV4_P], MSTPCR0, 15, 0, 1, 0),
-	MSTP("cmt0", &r_clk, MSTPCR0, 14, 0, 0, 0),
-	MSTP("rwdt0", &r_clk, MSTPCR0, 13, 0, 0, 0),
-	MSTP("dmac1", &div4_clks[DIV4_B], MSTPCR0, 12, 0, 1, 1),
-	MSTP("tmu1", &div4_clks[DIV4_P], MSTPCR0, 11, 0, 1, 0),
-	MSTP("flctl0", &div4_clks[DIV4_P], MSTPCR0, 10, 0, 1, 0),
-	MSTP("scif0", &div4_clks[DIV4_P], MSTPCR0, 9, 0, 1, 0),
-	MSTP("scif1", &div4_clks[DIV4_P], MSTPCR0, 8, 0, 1, 0),
-	MSTP("scif2", &div4_clks[DIV4_P], MSTPCR0, 7, 0, 1, 0),
-	MSTP("scif3", &div4_clks[DIV4_B], MSTPCR0, 6, 0, 1, 0),
-	MSTP("scif4", &div4_clks[DIV4_B], MSTPCR0, 5, 0, 1, 0),
-	MSTP("scif5", &div4_clks[DIV4_B], MSTPCR0, 4, 0, 1, 0),
-	MSTP("msiof0", &div4_clks[DIV4_B], MSTPCR0, 2, 0, 1, 0),
-	MSTP("msiof1", &div4_clks[DIV4_B], MSTPCR0, 1, 0, 1, 0),
-	MSTP("meram0", &div4_clks[DIV4_SH], MSTPCR0, 0, 1, 1, 0),
+	SH_HWBLK_CLK("tlb0", -1, I_CLK, HWBLK_TLB, CLK_ENABLE_ON_INIT),
+	SH_HWBLK_CLK("ic0", -1, I_CLK, HWBLK_IC, CLK_ENABLE_ON_INIT),
+	SH_HWBLK_CLK("oc0", -1, I_CLK, HWBLK_OC, CLK_ENABLE_ON_INIT),
+	SH_HWBLK_CLK("l2c0", -1, SH_CLK, HWBLK_L2C, CLK_ENABLE_ON_INIT),
+	SH_HWBLK_CLK("ilmem0", -1, I_CLK, HWBLK_ILMEM, CLK_ENABLE_ON_INIT),
+	SH_HWBLK_CLK("fpu0", -1, I_CLK, HWBLK_FPU, CLK_ENABLE_ON_INIT),
+	SH_HWBLK_CLK("intc0", -1, I_CLK, HWBLK_INTC, CLK_ENABLE_ON_INIT),
+	SH_HWBLK_CLK("dmac0", -1, B_CLK, HWBLK_DMAC0, 0),
+	SH_HWBLK_CLK("sh0", -1, SH_CLK, HWBLK_SHYWAY, CLK_ENABLE_ON_INIT),
+	SH_HWBLK_CLK("hudi0", -1, P_CLK, HWBLK_HUDI, 0),
+	SH_HWBLK_CLK("ubc0", -1, I_CLK, HWBLK_UBC, 0),
+	SH_HWBLK_CLK("tmu0", -1, P_CLK, HWBLK_TMU0, 0),
+	SH_HWBLK_CLK("cmt0", -1, R_CLK, HWBLK_CMT, 0),
+	SH_HWBLK_CLK("rwdt0", -1, R_CLK, HWBLK_RWDT, 0),
+	SH_HWBLK_CLK("dmac1", -1, B_CLK, HWBLK_DMAC1, 0),
+	SH_HWBLK_CLK("tmu1", -1, P_CLK, HWBLK_TMU1, 0),
+	SH_HWBLK_CLK("flctl0", -1, P_CLK, HWBLK_FLCTL, 0),
+	SH_HWBLK_CLK("scif0", -1, P_CLK, HWBLK_SCIF0, 0),
+	SH_HWBLK_CLK("scif1", -1, P_CLK, HWBLK_SCIF1, 0),
+	SH_HWBLK_CLK("scif2", -1, P_CLK, HWBLK_SCIF2, 0),
+	SH_HWBLK_CLK("scif3", -1, B_CLK, HWBLK_SCIF3, 0),
+	SH_HWBLK_CLK("scif4", -1, B_CLK, HWBLK_SCIF4, 0),
+	SH_HWBLK_CLK("scif5", -1, B_CLK, HWBLK_SCIF5, 0),
+	SH_HWBLK_CLK("msiof0", -1, B_CLK, HWBLK_MSIOF0, 0),
+	SH_HWBLK_CLK("msiof1", -1, B_CLK, HWBLK_MSIOF1, 0),
+	SH_HWBLK_CLK("meram0", -1, SH_CLK, HWBLK_MERAM, 0),
 
-	MSTP("i2c0", &div4_clks[DIV4_P], MSTPCR1, 9, 0, 1, 0),
-	MSTP("rtc0", &r_clk, MSTPCR1, 8, 0, 0, 0),
+	SH_HWBLK_CLK("i2c0", -1, P_CLK, HWBLK_IIC, 0),
+	SH_HWBLK_CLK("rtc0", -1, R_CLK, HWBLK_RTC, 0),
 
-	MSTP("atapi0", &div4_clks[DIV4_SH], MSTPCR2, 28, 0, 1, 0),
-	MSTP("adc0", &div4_clks[DIV4_P], MSTPCR2, 27, 0, 1, 0),
-	MSTP("tpu0", &div4_clks[DIV4_B], MSTPCR2, 25, 0, 1, 0),
-	MSTP("irda0", &div4_clks[DIV4_P], MSTPCR2, 24, 0, 1, 0),
-	MSTP("tsif0", &div4_clks[DIV4_B], MSTPCR2, 22, 0, 1, 0),
-	MSTP("icb0", &div4_clks[DIV4_B], MSTPCR2, 21, 0, 1, 1),
-	MSTP("sdhi0", &div4_clks[DIV4_B], MSTPCR2, 18, 0, 1, 0),
-	MSTP("sdhi1", &div4_clks[DIV4_B], MSTPCR2, 17, 0, 1, 0),
-	MSTP("keysc0", &r_clk, MSTPCR2, 14, 0, 0, 0),
-	MSTP("usb0", &div4_clks[DIV4_B], MSTPCR2, 11, 0, 1, 0),
-	MSTP("2dg0", &div4_clks[DIV4_B], MSTPCR2, 10, 0, 1, 1),
-	MSTP("siu0", &div4_clks[DIV4_B], MSTPCR2, 8, 0, 1, 0),
-	MSTP("veu1", &div4_clks[DIV4_B], MSTPCR2, 6, 1, 1, 1),
-	MSTP("vou0", &div4_clks[DIV4_B], MSTPCR2, 5, 0, 1, 1),
-	MSTP("beu0", &div4_clks[DIV4_B], MSTPCR2, 4, 0, 1, 1),
-	MSTP("ceu0", &div4_clks[DIV4_B], MSTPCR2, 3, 0, 1, 1),
-	MSTP("veu0", &div4_clks[DIV4_B], MSTPCR2, 2, 1, 1, 1),
-	MSTP("vpu0", &div4_clks[DIV4_B], MSTPCR2, 1, 1, 1, 1),
-	MSTP("lcdc0", &div4_clks[DIV4_B], MSTPCR2, 0, 0, 1, 1),
+	SH_HWBLK_CLK("atapi0", -1, SH_CLK, HWBLK_ATAPI, 0),
+	SH_HWBLK_CLK("adc0", -1, P_CLK, HWBLK_ADC, 0),
+	SH_HWBLK_CLK("tpu0", -1, B_CLK, HWBLK_TPU, 0),
+	SH_HWBLK_CLK("irda0", -1, P_CLK, HWBLK_IRDA, 0),
+	SH_HWBLK_CLK("tsif0", -1, B_CLK, HWBLK_TSIF, 0),
+	SH_HWBLK_CLK("icb0", -1, B_CLK, HWBLK_ICB, CLK_ENABLE_ON_INIT),
+	SH_HWBLK_CLK("sdhi0", -1, B_CLK, HWBLK_SDHI0, 0),
+	SH_HWBLK_CLK("sdhi1", -1, B_CLK, HWBLK_SDHI1, 0),
+	SH_HWBLK_CLK("keysc0", -1, R_CLK, HWBLK_KEYSC, 0),
+	SH_HWBLK_CLK("usb0", -1, B_CLK, HWBLK_USB, 0),
+	SH_HWBLK_CLK("2dg0", -1, B_CLK, HWBLK_2DG, 0),
+	SH_HWBLK_CLK("siu0", -1, B_CLK, HWBLK_SIU, 0),
+	SH_HWBLK_CLK("veu1", -1, B_CLK, HWBLK_VEU2H1, CLK_ENABLE_ON_INIT),
+	SH_HWBLK_CLK("vou0", -1, B_CLK, HWBLK_VOU, 0),
+	SH_HWBLK_CLK("beu0", -1, B_CLK, HWBLK_BEU, 0),
+	SH_HWBLK_CLK("ceu0", -1, B_CLK, HWBLK_CEU, 0),
+	SH_HWBLK_CLK("veu0", -1, B_CLK, HWBLK_VEU2H0, CLK_ENABLE_ON_INIT),
+	SH_HWBLK_CLK("vpu0", -1, B_CLK, HWBLK_VPU, CLK_ENABLE_ON_INIT),
+	SH_HWBLK_CLK("lcdc0", -1, B_CLK, HWBLK_LCDC, 0),
 };
 
 int __init arch_clk_init(void)
@@ -216,7 +219,7 @@ int __init arch_clk_init(void)
 		ret = sh_clk_div6_register(div6_clks, ARRAY_SIZE(div6_clks));
 
 	if (!ret)
-		ret = sh_clk_mstp32_register(mstp_clks, ARRAY_SIZE(mstp_clks));
+		ret = sh_hwblk_clk_register(mstp_clks, ARRAY_SIZE(mstp_clks));
 
 	return ret;
 }
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c
index 5d5c9b952883..34611d97378e 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c
@@ -22,6 +22,8 @@
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <asm/clock.h>
+#include <asm/hwblk.h>
+#include <cpu/sh7724.h>
 
 /* SH7724 registers */
 #define FRQCRA		0xa4150000
@@ -31,9 +33,6 @@
 #define FCLKBCR		0xa415000c
 #define IRDACLKCR	0xa4150018
 #define PLLCR		0xa4150024
-#define MSTPCR0		0xa4150030
-#define MSTPCR1		0xa4150034
-#define MSTPCR2		0xa4150038
 #define SPUCLKCR	0xa415003c
 #define FLLFRQ		0xa4150050
 #define LSTATS		0xa4150060
@@ -156,64 +155,67 @@ struct clk div6_clks[] = {
 	SH_CLK_DIV6("spu_clk", &div3_clk, SPUCLKCR, 0),
 };
 
-#define MSTP(_str, _parent, _reg, _bit, _force_on, _need_cpg, _need_ram) \
-  SH_CLK_MSTP32(_str, -1, _parent, _reg, _bit, _force_on * CLK_ENABLE_ON_INIT)
+#define R_CLK (&r_clk)
+#define P_CLK (&div4_clks[DIV4_P])
+#define B_CLK (&div4_clks[DIV4_B])
+#define I_CLK (&div4_clks[DIV4_I])
+#define SH_CLK (&div4_clks[DIV4_SH])
 
 static struct clk mstp_clks[] = {
-	MSTP("tlb0", &div4_clks[DIV4_I], MSTPCR0, 31, 1, 1, 0),
-	MSTP("ic0", &div4_clks[DIV4_I], MSTPCR0, 30, 1, 1, 0),
-	MSTP("oc0", &div4_clks[DIV4_I], MSTPCR0, 29, 1, 1, 0),
-	MSTP("rs0", &div4_clks[DIV4_B], MSTPCR0, 28, 1, 1, 0),
-	MSTP("ilmem0", &div4_clks[DIV4_I], MSTPCR0, 27, 1, 1, 0),
-	MSTP("l2c0", &div4_clks[DIV4_SH], MSTPCR0, 26, 1, 1, 0),
-	MSTP("fpu0", &div4_clks[DIV4_I], MSTPCR0, 24, 1, 1, 0),
-	MSTP("intc0", &div4_clks[DIV4_P], MSTPCR0, 22, 1, 1, 0),
-	MSTP("dmac0", &div4_clks[DIV4_B], MSTPCR0, 21, 0, 1, 1),
-	MSTP("sh0", &div4_clks[DIV4_SH], MSTPCR0, 20, 0, 1, 0),
-	MSTP("hudi0", &div4_clks[DIV4_P], MSTPCR0, 19, 0, 1, 0),
-	MSTP("ubc0", &div4_clks[DIV4_I], MSTPCR0, 17, 0, 1, 0),
-	MSTP("tmu0", &div4_clks[DIV4_P], MSTPCR0, 15, 0, 1, 0),
-	MSTP("cmt0", &r_clk, MSTPCR0, 14, 0, 0, 0),
-	MSTP("rwdt0", &r_clk, MSTPCR0, 13, 0, 0, 0),
-	MSTP("dmac1", &div4_clks[DIV4_B], MSTPCR0, 12, 0, 1, 1),
-	MSTP("tmu1", &div4_clks[DIV4_P], MSTPCR0, 10, 0, 1, 0),
-	MSTP("scif0", &div4_clks[DIV4_P], MSTPCR0, 9, 0, 1, 0),
-	MSTP("scif1", &div4_clks[DIV4_P], MSTPCR0, 8, 0, 1, 0),
-	MSTP("scif2", &div4_clks[DIV4_P], MSTPCR0, 7, 0, 1, 0),
-	MSTP("scif3", &div4_clks[DIV4_B], MSTPCR0, 6, 0, 1, 0),
-	MSTP("scif4", &div4_clks[DIV4_B], MSTPCR0, 5, 0, 1, 0),
-	MSTP("scif5", &div4_clks[DIV4_B], MSTPCR0, 4, 0, 1, 0),
-	MSTP("msiof0", &div4_clks[DIV4_B], MSTPCR0, 2, 0, 1, 0),
-	MSTP("msiof1", &div4_clks[DIV4_B], MSTPCR0, 1, 0, 1, 0),
+	SH_HWBLK_CLK("tlb0", -1, I_CLK, HWBLK_TLB, CLK_ENABLE_ON_INIT),
+	SH_HWBLK_CLK("ic0", -1, I_CLK, HWBLK_IC, CLK_ENABLE_ON_INIT),
+	SH_HWBLK_CLK("oc0", -1, I_CLK, HWBLK_OC, CLK_ENABLE_ON_INIT),
+	SH_HWBLK_CLK("rs0", -1, B_CLK, HWBLK_RSMEM, CLK_ENABLE_ON_INIT),
+	SH_HWBLK_CLK("ilmem0", -1, I_CLK, HWBLK_ILMEM, CLK_ENABLE_ON_INIT),
+	SH_HWBLK_CLK("l2c0", -1, SH_CLK, HWBLK_L2C, CLK_ENABLE_ON_INIT),
+	SH_HWBLK_CLK("fpu0", -1, I_CLK, HWBLK_FPU, CLK_ENABLE_ON_INIT),
+	SH_HWBLK_CLK("intc0", -1, P_CLK, HWBLK_INTC, CLK_ENABLE_ON_INIT),
+	SH_HWBLK_CLK("dmac0", -1, B_CLK, HWBLK_DMAC0, 0),
+	SH_HWBLK_CLK("sh0", -1, SH_CLK, HWBLK_SHYWAY, CLK_ENABLE_ON_INIT),
+	SH_HWBLK_CLK("hudi0", -1, P_CLK, HWBLK_HUDI, 0),
+	SH_HWBLK_CLK("ubc0", -1, I_CLK, HWBLK_UBC, 0),
+	SH_HWBLK_CLK("tmu0", -1, P_CLK, HWBLK_TMU0, 0),
+	SH_HWBLK_CLK("cmt0", -1, R_CLK, HWBLK_CMT, 0),
+	SH_HWBLK_CLK("rwdt0", -1, R_CLK, HWBLK_RWDT, 0),
+	SH_HWBLK_CLK("dmac1", -1, B_CLK, HWBLK_DMAC1, 0),
+	SH_HWBLK_CLK("tmu1", -1, P_CLK, HWBLK_TMU1, 0),
+	SH_HWBLK_CLK("scif0", -1, P_CLK, HWBLK_SCIF0, 0),
+	SH_HWBLK_CLK("scif1", -1, P_CLK, HWBLK_SCIF1, 0),
+	SH_HWBLK_CLK("scif2", -1, P_CLK, HWBLK_SCIF2, 0),
+	SH_HWBLK_CLK("scif3", -1, B_CLK, HWBLK_SCIF3, 0),
+	SH_HWBLK_CLK("scif4", -1, B_CLK, HWBLK_SCIF4, 0),
+	SH_HWBLK_CLK("scif5", -1, B_CLK, HWBLK_SCIF5, 0),
+	SH_HWBLK_CLK("msiof0", -1, B_CLK, HWBLK_MSIOF0, 0),
+	SH_HWBLK_CLK("msiof1", -1, B_CLK, HWBLK_MSIOF1, 0),
 
-	MSTP("keysc0", &r_clk, MSTPCR1, 12, 0, 0, 0),
-	MSTP("rtc0", &r_clk, MSTPCR1, 11, 0, 0, 0),
-	MSTP("i2c0", &div4_clks[DIV4_P], MSTPCR1, 9, 0, 1, 0),
-	MSTP("i2c1", &div4_clks[DIV4_P], MSTPCR1, 8, 0, 1, 0),
+	SH_HWBLK_CLK("keysc0", -1, R_CLK, HWBLK_KEYSC, 0),
+	SH_HWBLK_CLK("rtc0", -1, R_CLK, HWBLK_RTC, 0),
+	SH_HWBLK_CLK("i2c0", -1, P_CLK, HWBLK_IIC0, 0),
+	SH_HWBLK_CLK("i2c1", -1, P_CLK, HWBLK_IIC1, 0),
 
-	MSTP("mmc0", &div4_clks[DIV4_B], MSTPCR2, 29, 0, 1, 0),
-	MSTP("eth0", &div4_clks[DIV4_B], MSTPCR2, 28, 0, 1, 0),
-	MSTP("atapi0", &div4_clks[DIV4_B], MSTPCR2, 26, 0, 1, 0),
-	MSTP("tpu0", &div4_clks[DIV4_B], MSTPCR2, 25, 0, 1, 0),
-	MSTP("irda0", &div4_clks[DIV4_P], MSTPCR2, 24, 0, 1, 0),
-	MSTP("tsif0", &div4_clks[DIV4_B], MSTPCR2, 22, 0, 1, 0),
-	MSTP("usb1", &div4_clks[DIV4_B], MSTPCR2, 21, 0, 1, 1),
-	MSTP("usb0", &div4_clks[DIV4_B], MSTPCR2, 20, 0, 1, 1),
-	MSTP("2dg0", &div4_clks[DIV4_B], MSTPCR2, 19, 0, 1, 1),
-	MSTP("sdhi0", &div4_clks[DIV4_B], MSTPCR2, 18, 0, 1, 0),
-	MSTP("sdhi1", &div4_clks[DIV4_B], MSTPCR2, 17, 0, 1, 0),
-	MSTP("veu1", &div4_clks[DIV4_B], MSTPCR2, 15, 1, 1, 1),
-	MSTP("ceu1", &div4_clks[DIV4_B], MSTPCR2, 13, 0, 1, 1),
-	MSTP("beu1", &div4_clks[DIV4_B], MSTPCR2, 12, 0, 1, 1),
-	MSTP("2ddmac0", &div4_clks[DIV4_SH], MSTPCR2, 10, 0, 1, 1),
-	MSTP("spu0", &div4_clks[DIV4_B], MSTPCR2, 9, 0, 1, 0),
-	MSTP("jpu0", &div4_clks[DIV4_B], MSTPCR2, 6, 1, 1, 1),
-	MSTP("vou0", &div4_clks[DIV4_B], MSTPCR2, 5, 0, 1, 1),
-	MSTP("beu0", &div4_clks[DIV4_B], MSTPCR2, 4, 0, 1, 1),
-	MSTP("ceu0", &div4_clks[DIV4_B], MSTPCR2, 3, 0, 1, 1),
-	MSTP("veu0", &div4_clks[DIV4_B], MSTPCR2, 2, 1, 1, 1),
-	MSTP("vpu0", &div4_clks[DIV4_B], MSTPCR2, 1, 1, 1, 1),
-	MSTP("lcdc0", &div4_clks[DIV4_B], MSTPCR2, 0, 0, 1, 1),
+	SH_HWBLK_CLK("mmc0", -1, B_CLK, HWBLK_MMC, 0),
+	SH_HWBLK_CLK("eth0", -1, B_CLK, HWBLK_ETHER, 0),
+	SH_HWBLK_CLK("atapi0", -1, B_CLK, HWBLK_ATAPI, 0),
+	SH_HWBLK_CLK("tpu0", -1, B_CLK, HWBLK_TPU, 0),
+	SH_HWBLK_CLK("irda0", -1, P_CLK, HWBLK_IRDA, 0),
+	SH_HWBLK_CLK("tsif0", -1, B_CLK, HWBLK_TSIF, 0),
+	SH_HWBLK_CLK("usb1", -1, B_CLK, HWBLK_USB1, 0),
+	SH_HWBLK_CLK("usb0", -1, B_CLK, HWBLK_USB0, 0),
+	SH_HWBLK_CLK("2dg0", -1, B_CLK, HWBLK_2DG, 0),
+	SH_HWBLK_CLK("sdhi0", -1, B_CLK, HWBLK_SDHI0, 0),
+	SH_HWBLK_CLK("sdhi1", -1, B_CLK, HWBLK_SDHI1, 0),
+	SH_HWBLK_CLK("veu1", -1, B_CLK, HWBLK_VEU1, CLK_ENABLE_ON_INIT),
+	SH_HWBLK_CLK("ceu1", -1, B_CLK, HWBLK_CEU1, 0),
+	SH_HWBLK_CLK("beu1", -1, B_CLK, HWBLK_BEU1, 0),
+	SH_HWBLK_CLK("2ddmac0", -1, SH_CLK, HWBLK_2DDMAC, 0),
+	SH_HWBLK_CLK("spu0", -1, B_CLK, HWBLK_SPU, 0),
+	SH_HWBLK_CLK("jpu0", -1, B_CLK, HWBLK_JPU, CLK_ENABLE_ON_INIT),
+	SH_HWBLK_CLK("vou0", -1, B_CLK, HWBLK_VOU, 0),
+	SH_HWBLK_CLK("beu0", -1, B_CLK, HWBLK_BEU0, 0),
+	SH_HWBLK_CLK("ceu0", -1, B_CLK, HWBLK_CEU0, 0),
+	SH_HWBLK_CLK("veu0", -1, B_CLK, HWBLK_VEU0, CLK_ENABLE_ON_INIT),
+	SH_HWBLK_CLK("vpu0", -1, B_CLK, HWBLK_VPU, CLK_ENABLE_ON_INIT),
+	SH_HWBLK_CLK("lcdc0", -1, B_CLK, HWBLK_LCDC, 0),
 };
 
 int __init arch_clk_init(void)
@@ -236,7 +238,7 @@ int __init arch_clk_init(void)
 		ret = sh_clk_div6_register(div6_clks, ARRAY_SIZE(div6_clks));
 
 	if (!ret)
-		ret = sh_clk_mstp32_register(mstp_clks, ARRAY_SIZE(mstp_clks));
+		ret = sh_hwblk_clk_register(mstp_clks, ARRAY_SIZE(mstp_clks));
 
 	return ret;
 }
diff --git a/arch/sh/kernel/cpu/sh4a/hwblk-sh7722.c b/arch/sh/kernel/cpu/sh4a/hwblk-sh7722.c
new file mode 100644
index 000000000000..a288b5d92341
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/hwblk-sh7722.c
@@ -0,0 +1,106 @@
+/*
+ * arch/sh/kernel/cpu/sh4a/hwblk-sh7722.c
+ *
+ * SH7722 hardware block support
+ *
+ * Copyright (C) 2009 Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <asm/suspend.h>
+#include <asm/hwblk.h>
+#include <cpu/sh7722.h>
+
+/* SH7722 registers */
+#define MSTPCR0		0xa4150030
+#define MSTPCR1		0xa4150034
+#define MSTPCR2		0xa4150038
+
+/* SH7722 Power Domains */
+enum { CORE_AREA, SUB_AREA, CORE_AREA_BM };
+static struct hwblk_area sh7722_hwblk_area[] = {
+	[CORE_AREA] = HWBLK_AREA(0, 0),
+	[CORE_AREA_BM] = HWBLK_AREA(HWBLK_AREA_FLAG_PARENT, CORE_AREA),
+	[SUB_AREA] = HWBLK_AREA(0, 0),
+};
+
+/* Table mapping HWBLK to Module Stop Bit and Power Domain */
+static struct hwblk sh7722_hwblk[HWBLK_NR] = {
+	[HWBLK_TLB] = HWBLK(MSTPCR0, 31, CORE_AREA),
+	[HWBLK_IC] = HWBLK(MSTPCR0, 30, CORE_AREA),
+	[HWBLK_OC] = HWBLK(MSTPCR0, 29, CORE_AREA),
+	[HWBLK_URAM] = HWBLK(MSTPCR0, 28, CORE_AREA),
+	[HWBLK_XYMEM] = HWBLK(MSTPCR0, 26, CORE_AREA),
+	[HWBLK_INTC] = HWBLK(MSTPCR0, 22, CORE_AREA),
+	[HWBLK_DMAC] = HWBLK(MSTPCR0, 21, CORE_AREA_BM),
+	[HWBLK_SHYWAY] = HWBLK(MSTPCR0, 20, CORE_AREA),
+	[HWBLK_HUDI] = HWBLK(MSTPCR0, 19, CORE_AREA),
+	[HWBLK_UBC] = HWBLK(MSTPCR0, 17, CORE_AREA),
+	[HWBLK_TMU] = HWBLK(MSTPCR0, 15, CORE_AREA),
+	[HWBLK_CMT] = HWBLK(MSTPCR0, 14, SUB_AREA),
+	[HWBLK_RWDT] = HWBLK(MSTPCR0, 13, SUB_AREA),
+	[HWBLK_FLCTL] = HWBLK(MSTPCR0, 10, CORE_AREA),
+	[HWBLK_SCIF0] = HWBLK(MSTPCR0, 7, CORE_AREA),
+	[HWBLK_SCIF1] = HWBLK(MSTPCR0, 6, CORE_AREA),
+	[HWBLK_SCIF2] = HWBLK(MSTPCR0, 5, CORE_AREA),
+	[HWBLK_SIO] = HWBLK(MSTPCR0, 3, CORE_AREA),
+	[HWBLK_SIOF0] = HWBLK(MSTPCR0, 2, CORE_AREA),
+	[HWBLK_SIOF1] = HWBLK(MSTPCR0, 1, CORE_AREA),
+
+	[HWBLK_IIC] = HWBLK(MSTPCR1, 9, CORE_AREA),
+	[HWBLK_RTC] = HWBLK(MSTPCR1, 8, SUB_AREA),
+
+	[HWBLK_TPU] = HWBLK(MSTPCR2, 25, CORE_AREA),
+	[HWBLK_IRDA] = HWBLK(MSTPCR2, 24, CORE_AREA),
+	[HWBLK_SDHI] = HWBLK(MSTPCR2, 18, CORE_AREA),
+	[HWBLK_SIM] = HWBLK(MSTPCR2, 16, CORE_AREA),
+	[HWBLK_KEYSC] = HWBLK(MSTPCR2, 14, SUB_AREA),
+	[HWBLK_TSIF] = HWBLK(MSTPCR2, 13, SUB_AREA),
+	[HWBLK_USBF] = HWBLK(MSTPCR2, 11, CORE_AREA),
+	[HWBLK_2DG] = HWBLK(MSTPCR2, 9, CORE_AREA_BM),
+	[HWBLK_SIU] = HWBLK(MSTPCR2, 8, CORE_AREA),
+	[HWBLK_JPU] = HWBLK(MSTPCR2, 6, CORE_AREA_BM),
+	[HWBLK_VOU] = HWBLK(MSTPCR2, 5, CORE_AREA_BM),
+	[HWBLK_BEU] = HWBLK(MSTPCR2, 4, CORE_AREA_BM),
+	[HWBLK_CEU] = HWBLK(MSTPCR2, 3, CORE_AREA_BM),
+	[HWBLK_VEU] = HWBLK(MSTPCR2, 2, CORE_AREA_BM),
+	[HWBLK_VPU] = HWBLK(MSTPCR2, 1, CORE_AREA_BM),
+	[HWBLK_LCDC] = HWBLK(MSTPCR2, 0, CORE_AREA_BM),
+};
+
+static struct hwblk_info sh7722_hwblk_info = {
+	.areas = sh7722_hwblk_area,
+	.nr_areas = ARRAY_SIZE(sh7722_hwblk_area),
+	.hwblks = sh7722_hwblk,
+	.nr_hwblks = ARRAY_SIZE(sh7722_hwblk),
+};
+
+int arch_hwblk_sleep_mode(void)
+{
+	if (!sh7722_hwblk_area[CORE_AREA].cnt[HWBLK_CNT_USAGE])
+		return SUSP_SH_STANDBY | SUSP_SH_SF;
+
+	if (!sh7722_hwblk_area[CORE_AREA_BM].cnt[HWBLK_CNT_USAGE])
+		return SUSP_SH_SLEEP | SUSP_SH_SF;
+
+	return SUSP_SH_SLEEP;
+}
+
+int __init arch_hwblk_init(void)
+{
+	return hwblk_register(&sh7722_hwblk_info);
+}
diff --git a/arch/sh/kernel/cpu/sh4a/hwblk-sh7723.c b/arch/sh/kernel/cpu/sh4a/hwblk-sh7723.c
new file mode 100644
index 000000000000..a7f4684d2032
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/hwblk-sh7723.c
@@ -0,0 +1,117 @@
+/*
+ * arch/sh/kernel/cpu/sh4a/hwblk-sh7723.c
+ *
+ * SH7723 hardware block support
+ *
+ * Copyright (C) 2009 Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <asm/suspend.h>
+#include <asm/hwblk.h>
+#include <cpu/sh7723.h>
+
+/* SH7723 registers */
+#define MSTPCR0		0xa4150030
+#define MSTPCR1		0xa4150034
+#define MSTPCR2		0xa4150038
+
+/* SH7723 Power Domains */
+enum { CORE_AREA, SUB_AREA, CORE_AREA_BM };
+static struct hwblk_area sh7723_hwblk_area[] = {
+	[CORE_AREA] = HWBLK_AREA(0, 0),
+	[CORE_AREA_BM] = HWBLK_AREA(HWBLK_AREA_FLAG_PARENT, CORE_AREA),
+	[SUB_AREA] = HWBLK_AREA(0, 0),
+};
+
+/* Table mapping HWBLK to Module Stop Bit and Power Domain */
+static struct hwblk sh7723_hwblk[HWBLK_NR] = {
+	[HWBLK_TLB] = HWBLK(MSTPCR0, 31, CORE_AREA),
+	[HWBLK_IC] = HWBLK(MSTPCR0, 30, CORE_AREA),
+	[HWBLK_OC] = HWBLK(MSTPCR0, 29, CORE_AREA),
+	[HWBLK_L2C] = HWBLK(MSTPCR0, 28, CORE_AREA),
+	[HWBLK_ILMEM] = HWBLK(MSTPCR0, 27, CORE_AREA),
+	[HWBLK_FPU] = HWBLK(MSTPCR0, 24, CORE_AREA),
+	[HWBLK_INTC] = HWBLK(MSTPCR0, 22, CORE_AREA),
+	[HWBLK_DMAC0] = HWBLK(MSTPCR0, 21, CORE_AREA_BM),
+	[HWBLK_SHYWAY] = HWBLK(MSTPCR0, 20, CORE_AREA),
+	[HWBLK_HUDI] = HWBLK(MSTPCR0, 19, CORE_AREA),
+	[HWBLK_DBG] = HWBLK(MSTPCR0, 18, CORE_AREA),
+	[HWBLK_UBC] = HWBLK(MSTPCR0, 17, CORE_AREA),
+	[HWBLK_SUBC] = HWBLK(MSTPCR0, 16, CORE_AREA),
+	[HWBLK_TMU0] = HWBLK(MSTPCR0, 15, CORE_AREA),
+	[HWBLK_CMT] = HWBLK(MSTPCR0, 14, SUB_AREA),
+	[HWBLK_RWDT] = HWBLK(MSTPCR0, 13, SUB_AREA),
+	[HWBLK_DMAC1] = HWBLK(MSTPCR0, 12, CORE_AREA_BM),
+	[HWBLK_TMU1] = HWBLK(MSTPCR0, 11, CORE_AREA),
+	[HWBLK_FLCTL] = HWBLK(MSTPCR0, 10, CORE_AREA),
+	[HWBLK_SCIF0] = HWBLK(MSTPCR0, 9, CORE_AREA),
+	[HWBLK_SCIF1] = HWBLK(MSTPCR0, 8, CORE_AREA),
+	[HWBLK_SCIF2] = HWBLK(MSTPCR0, 7, CORE_AREA),
+	[HWBLK_SCIF3] = HWBLK(MSTPCR0, 6, CORE_AREA),
+	[HWBLK_SCIF4] = HWBLK(MSTPCR0, 5, CORE_AREA),
+	[HWBLK_SCIF5] = HWBLK(MSTPCR0, 4, CORE_AREA),
+	[HWBLK_MSIOF0] = HWBLK(MSTPCR0, 2, CORE_AREA),
+	[HWBLK_MSIOF1] = HWBLK(MSTPCR0, 1, CORE_AREA),
+	[HWBLK_MERAM] = HWBLK(MSTPCR0, 0, CORE_AREA),
+
+	[HWBLK_IIC] = HWBLK(MSTPCR1, 9, CORE_AREA),
+	[HWBLK_RTC] = HWBLK(MSTPCR1, 8, SUB_AREA),
+
+	[HWBLK_ATAPI] = HWBLK(MSTPCR2, 28, CORE_AREA_BM),
+	[HWBLK_ADC] = HWBLK(MSTPCR2, 27, CORE_AREA),
+	[HWBLK_TPU] = HWBLK(MSTPCR2, 25, CORE_AREA),
+	[HWBLK_IRDA] = HWBLK(MSTPCR2, 24, CORE_AREA),
+	[HWBLK_TSIF] = HWBLK(MSTPCR2, 22, CORE_AREA),
+	[HWBLK_ICB] = HWBLK(MSTPCR2, 21, CORE_AREA_BM),
+	[HWBLK_SDHI0] = HWBLK(MSTPCR2, 18, CORE_AREA),
+	[HWBLK_SDHI1] = HWBLK(MSTPCR2, 17, CORE_AREA),
+	[HWBLK_KEYSC] = HWBLK(MSTPCR2, 14, SUB_AREA),
+	[HWBLK_USB] = HWBLK(MSTPCR2, 11, CORE_AREA),
+	[HWBLK_2DG] = HWBLK(MSTPCR2, 10, CORE_AREA_BM),
+	[HWBLK_SIU] = HWBLK(MSTPCR2, 8, CORE_AREA),
+	[HWBLK_VEU2H1] = HWBLK(MSTPCR2, 6, CORE_AREA_BM),
+	[HWBLK_VOU] = HWBLK(MSTPCR2, 5, CORE_AREA_BM),
+	[HWBLK_BEU] = HWBLK(MSTPCR2, 4, CORE_AREA_BM),
+	[HWBLK_CEU] = HWBLK(MSTPCR2, 3, CORE_AREA_BM),
+	[HWBLK_VEU2H0] = HWBLK(MSTPCR2, 2, CORE_AREA_BM),
+	[HWBLK_VPU] = HWBLK(MSTPCR2, 1, CORE_AREA_BM),
+	[HWBLK_LCDC] = HWBLK(MSTPCR2, 0, CORE_AREA_BM),
+};
+
+static struct hwblk_info sh7723_hwblk_info = {
+	.areas = sh7723_hwblk_area,
+	.nr_areas = ARRAY_SIZE(sh7723_hwblk_area),
+	.hwblks = sh7723_hwblk,
+	.nr_hwblks = ARRAY_SIZE(sh7723_hwblk),
+};
+
+int arch_hwblk_sleep_mode(void)
+{
+	if (!sh7723_hwblk_area[CORE_AREA].cnt[HWBLK_CNT_USAGE])
+		return SUSP_SH_STANDBY | SUSP_SH_SF;
+
+	if (!sh7723_hwblk_area[CORE_AREA_BM].cnt[HWBLK_CNT_USAGE])
+		return SUSP_SH_SLEEP | SUSP_SH_SF;
+
+	return SUSP_SH_SLEEP;
+}
+
+int __init arch_hwblk_init(void)
+{
+	return hwblk_register(&sh7723_hwblk_info);
+}
diff --git a/arch/sh/kernel/cpu/sh4a/hwblk-sh7724.c b/arch/sh/kernel/cpu/sh4a/hwblk-sh7724.c
new file mode 100644
index 000000000000..1613ad6013c3
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/hwblk-sh7724.c
@@ -0,0 +1,121 @@
+/*
+ * arch/sh/kernel/cpu/sh4a/hwblk-sh7724.c
+ *
+ * SH7724 hardware block support
+ *
+ * Copyright (C) 2009 Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <asm/suspend.h>
+#include <asm/hwblk.h>
+#include <cpu/sh7724.h>
+
+/* SH7724 registers */
+#define MSTPCR0		0xa4150030
+#define MSTPCR1		0xa4150034
+#define MSTPCR2		0xa4150038
+
+/* SH7724 Power Domains */
+enum { CORE_AREA, SUB_AREA, CORE_AREA_BM };
+static struct hwblk_area sh7724_hwblk_area[] = {
+	[CORE_AREA] = HWBLK_AREA(0, 0),
+	[CORE_AREA_BM] = HWBLK_AREA(HWBLK_AREA_FLAG_PARENT, CORE_AREA),
+	[SUB_AREA] = HWBLK_AREA(0, 0),
+};
+
+/* Table mapping HWBLK to Module Stop Bit and Power Domain */
+static struct hwblk sh7724_hwblk[HWBLK_NR] = {
+	[HWBLK_TLB] = HWBLK(MSTPCR0, 31, CORE_AREA),
+	[HWBLK_IC] = HWBLK(MSTPCR0, 30, CORE_AREA),
+	[HWBLK_OC] = HWBLK(MSTPCR0, 29, CORE_AREA),
+	[HWBLK_RSMEM] = HWBLK(MSTPCR0, 28, CORE_AREA),
+	[HWBLK_ILMEM] = HWBLK(MSTPCR0, 27, CORE_AREA),
+	[HWBLK_L2C] = HWBLK(MSTPCR0, 26, CORE_AREA),
+	[HWBLK_FPU] = HWBLK(MSTPCR0, 24, CORE_AREA),
+	[HWBLK_INTC] = HWBLK(MSTPCR0, 22, CORE_AREA),
+	[HWBLK_DMAC0] = HWBLK(MSTPCR0, 21, CORE_AREA_BM),
+	[HWBLK_SHYWAY] = HWBLK(MSTPCR0, 20, CORE_AREA),
+	[HWBLK_HUDI] = HWBLK(MSTPCR0, 19, CORE_AREA),
+	[HWBLK_DBG] = HWBLK(MSTPCR0, 18, CORE_AREA),
+	[HWBLK_UBC] = HWBLK(MSTPCR0, 17, CORE_AREA),
+	[HWBLK_TMU0] = HWBLK(MSTPCR0, 15, CORE_AREA),
+	[HWBLK_CMT] = HWBLK(MSTPCR0, 14, SUB_AREA),
+	[HWBLK_RWDT] = HWBLK(MSTPCR0, 13, SUB_AREA),
+	[HWBLK_DMAC1] = HWBLK(MSTPCR0, 12, CORE_AREA_BM),
+	[HWBLK_TMU1] = HWBLK(MSTPCR0, 10, CORE_AREA),
+	[HWBLK_SCIF0] = HWBLK(MSTPCR0, 9, CORE_AREA),
+	[HWBLK_SCIF1] = HWBLK(MSTPCR0, 8, CORE_AREA),
+	[HWBLK_SCIF2] = HWBLK(MSTPCR0, 7, CORE_AREA),
+	[HWBLK_SCIF3] = HWBLK(MSTPCR0, 6, CORE_AREA),
+	[HWBLK_SCIF4] = HWBLK(MSTPCR0, 5, CORE_AREA),
+	[HWBLK_SCIF5] = HWBLK(MSTPCR0, 4, CORE_AREA),
+	[HWBLK_MSIOF0] = HWBLK(MSTPCR0, 2, CORE_AREA),
+	[HWBLK_MSIOF1] = HWBLK(MSTPCR0, 1, CORE_AREA),
+
+	[HWBLK_KEYSC] = HWBLK(MSTPCR1, 12, SUB_AREA),
+	[HWBLK_RTC] = HWBLK(MSTPCR1, 11, SUB_AREA),
+	[HWBLK_IIC0] = HWBLK(MSTPCR1, 9, CORE_AREA),
+	[HWBLK_IIC1] = HWBLK(MSTPCR1, 8, CORE_AREA),
+
+	[HWBLK_MMC] = HWBLK(MSTPCR2, 29, CORE_AREA),
+	[HWBLK_ETHER] = HWBLK(MSTPCR2, 28, CORE_AREA_BM),
+	[HWBLK_ATAPI] = HWBLK(MSTPCR2, 26, CORE_AREA_BM),
+	[HWBLK_TPU] = HWBLK(MSTPCR2, 25, CORE_AREA),
+	[HWBLK_IRDA] = HWBLK(MSTPCR2, 24, CORE_AREA),
+	[HWBLK_TSIF] = HWBLK(MSTPCR2, 22, CORE_AREA),
+	[HWBLK_USB1] = HWBLK(MSTPCR2, 21, CORE_AREA),
+	[HWBLK_USB0] = HWBLK(MSTPCR2, 20, CORE_AREA),
+	[HWBLK_2DG] = HWBLK(MSTPCR2, 19, CORE_AREA_BM),
+	[HWBLK_SDHI0] = HWBLK(MSTPCR2, 18, CORE_AREA),
+	[HWBLK_SDHI1] = HWBLK(MSTPCR2, 17, CORE_AREA),
+	[HWBLK_VEU1] = HWBLK(MSTPCR2, 15, CORE_AREA_BM),
+	[HWBLK_CEU1] = HWBLK(MSTPCR2, 13, CORE_AREA_BM),
+	[HWBLK_BEU1] = HWBLK(MSTPCR2, 12, CORE_AREA_BM),
+	[HWBLK_2DDMAC] = HWBLK(MSTPCR2, 10, CORE_AREA_BM),
+	[HWBLK_SPU] = HWBLK(MSTPCR2, 9, CORE_AREA_BM),
+	[HWBLK_JPU] = HWBLK(MSTPCR2, 6, CORE_AREA_BM),
+	[HWBLK_VOU] = HWBLK(MSTPCR2, 5, CORE_AREA_BM),
+	[HWBLK_BEU0] = HWBLK(MSTPCR2, 4, CORE_AREA_BM),
+	[HWBLK_CEU0] = HWBLK(MSTPCR2, 3, CORE_AREA_BM),
+	[HWBLK_VEU0] = HWBLK(MSTPCR2, 2, CORE_AREA_BM),
+	[HWBLK_VPU] = HWBLK(MSTPCR2, 1, CORE_AREA_BM),
+	[HWBLK_LCDC] = HWBLK(MSTPCR2, 0, CORE_AREA_BM),
+};
+
+static struct hwblk_info sh7724_hwblk_info = {
+	.areas = sh7724_hwblk_area,
+	.nr_areas = ARRAY_SIZE(sh7724_hwblk_area),
+	.hwblks = sh7724_hwblk,
+	.nr_hwblks = ARRAY_SIZE(sh7724_hwblk),
+};
+
+int arch_hwblk_sleep_mode(void)
+{
+	if (!sh7724_hwblk_area[CORE_AREA].cnt[HWBLK_CNT_USAGE])
+		return SUSP_SH_STANDBY | SUSP_SH_SF;
+
+	if (!sh7724_hwblk_area[CORE_AREA_BM].cnt[HWBLK_CNT_USAGE])
+		return SUSP_SH_SLEEP | SUSP_SH_SF;
+
+	return SUSP_SH_SLEEP;
+}
+
+int __init arch_hwblk_init(void)
+{
+	return hwblk_register(&sh7724_hwblk_info);
+}
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c
index 1a956b1beccc..4a9010bf4fd3 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c
@@ -40,7 +40,7 @@ static struct platform_device iic_device = {
 };
 
 static struct r8a66597_platdata r8a66597_data = {
-	/* This set zero to all members */
+	.on_chip = 1,
 };
 
 static struct resource usb_host_resources[] = {
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
index cda76ebf87c3..35097753456c 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
@@ -13,9 +13,11 @@
 #include <linux/serial_sci.h>
 #include <linux/mm.h>
 #include <linux/uio_driver.h>
+#include <linux/usb/m66592.h>
 #include <linux/sh_timer.h>
 #include <asm/clock.h>
 #include <asm/mmzone.h>
+#include <cpu/sh7722.h>
 
 static struct resource rtc_resources[] = {
 	[0] = {
@@ -45,11 +47,18 @@ static struct platform_device rtc_device = {
 	.id		= -1,
 	.num_resources	= ARRAY_SIZE(rtc_resources),
 	.resource	= rtc_resources,
+	.archdata = {
+		.hwblk_id = HWBLK_RTC,
+	},
+};
+
+static struct m66592_platdata usbf_platdata = {
+	.on_chip = 1,
 };
 
 static struct resource usbf_resources[] = {
 	[0] = {
-		.name	= "m66592_udc",
+		.name	= "USBF",
 		.start	= 0x04480000,
 		.end	= 0x044800FF,
 		.flags	= IORESOURCE_MEM,
@@ -67,9 +76,13 @@ static struct platform_device usbf_device = {
 	.dev = {
 		.dma_mask		= NULL,
 		.coherent_dma_mask	= 0xffffffff,
+		.platform_data		= &usbf_platdata,
 	},
 	.num_resources	= ARRAY_SIZE(usbf_resources),
 	.resource	= usbf_resources,
+	.archdata = {
+		.hwblk_id = HWBLK_USBF,
+	},
 };
 
 static struct resource iic_resources[] = {
@@ -91,6 +104,9 @@ static struct platform_device iic_device = {
 	.id             = 0, /* "i2c0" clock */
 	.num_resources  = ARRAY_SIZE(iic_resources),
 	.resource       = iic_resources,
+	.archdata = {
+		.hwblk_id = HWBLK_IIC,
+	},
 };
 
 static struct uio_info vpu_platform_data = {
@@ -119,6 +135,9 @@ static struct platform_device vpu_device = {
 	},
 	.resource	= vpu_resources,
 	.num_resources	= ARRAY_SIZE(vpu_resources),
+	.archdata = {
+		.hwblk_id = HWBLK_VPU,
+	},
 };
 
 static struct uio_info veu_platform_data = {
@@ -147,6 +166,9 @@ static struct platform_device veu_device = {
 	},
 	.resource	= veu_resources,
 	.num_resources	= ARRAY_SIZE(veu_resources),
+	.archdata = {
+		.hwblk_id = HWBLK_VEU,
+	},
 };
 
 static struct uio_info jpu_platform_data = {
@@ -175,6 +197,9 @@ static struct platform_device jpu_device = {
 	},
 	.resource	= jpu_resources,
 	.num_resources	= ARRAY_SIZE(jpu_resources),
+	.archdata = {
+		.hwblk_id = HWBLK_JPU,
+	},
 };
 
 static struct sh_timer_config cmt_platform_data = {
@@ -207,6 +232,9 @@ static struct platform_device cmt_device = {
 	},
 	.resource	= cmt_resources,
 	.num_resources	= ARRAY_SIZE(cmt_resources),
+	.archdata = {
+		.hwblk_id = HWBLK_CMT,
+	},
 };
 
 static struct sh_timer_config tmu0_platform_data = {
@@ -238,6 +266,9 @@ static struct platform_device tmu0_device = {
 	},
 	.resource	= tmu0_resources,
 	.num_resources	= ARRAY_SIZE(tmu0_resources),
+	.archdata = {
+		.hwblk_id = HWBLK_TMU,
+	},
 };
 
 static struct sh_timer_config tmu1_platform_data = {
@@ -269,6 +300,9 @@ static struct platform_device tmu1_device = {
 	},
 	.resource	= tmu1_resources,
 	.num_resources	= ARRAY_SIZE(tmu1_resources),
+	.archdata = {
+		.hwblk_id = HWBLK_TMU,
+	},
 };
 
 static struct sh_timer_config tmu2_platform_data = {
@@ -299,6 +333,9 @@ static struct platform_device tmu2_device = {
 	},
 	.resource	= tmu2_resources,
 	.num_resources	= ARRAY_SIZE(tmu2_resources),
+	.archdata = {
+		.hwblk_id = HWBLK_TMU,
+	},
 };
 
 static struct plat_sci_port sci_platform_data[] = {
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
index b45dace9539f..4caa5a7ca86e 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
@@ -18,6 +18,7 @@
 #include <linux/io.h>
 #include <asm/clock.h>
 #include <asm/mmzone.h>
+#include <cpu/sh7723.h>
 
 static struct uio_info vpu_platform_data = {
 	.name = "VPU5",
@@ -45,6 +46,9 @@ static struct platform_device vpu_device = {
 	},
 	.resource	= vpu_resources,
 	.num_resources	= ARRAY_SIZE(vpu_resources),
+	.archdata = {
+		.hwblk_id = HWBLK_VPU,
+	},
 };
 
 static struct uio_info veu0_platform_data = {
@@ -73,6 +77,9 @@ static struct platform_device veu0_device = {
 	},
 	.resource	= veu0_resources,
 	.num_resources	= ARRAY_SIZE(veu0_resources),
+	.archdata = {
+		.hwblk_id = HWBLK_VEU2H0,
+	},
 };
 
 static struct uio_info veu1_platform_data = {
@@ -101,6 +108,9 @@ static struct platform_device veu1_device = {
 	},
 	.resource	= veu1_resources,
 	.num_resources	= ARRAY_SIZE(veu1_resources),
+	.archdata = {
+		.hwblk_id = HWBLK_VEU2H1,
+	},
 };
 
 static struct sh_timer_config cmt_platform_data = {
@@ -133,6 +143,9 @@ static struct platform_device cmt_device = {
 	},
 	.resource	= cmt_resources,
 	.num_resources	= ARRAY_SIZE(cmt_resources),
+	.archdata = {
+		.hwblk_id = HWBLK_CMT,
+	},
 };
 
 static struct sh_timer_config tmu0_platform_data = {
@@ -164,6 +177,9 @@ static struct platform_device tmu0_device = {
 	},
 	.resource	= tmu0_resources,
 	.num_resources	= ARRAY_SIZE(tmu0_resources),
+	.archdata = {
+		.hwblk_id = HWBLK_TMU0,
+	},
 };
 
 static struct sh_timer_config tmu1_platform_data = {
@@ -195,6 +211,9 @@ static struct platform_device tmu1_device = {
 	},
 	.resource	= tmu1_resources,
 	.num_resources	= ARRAY_SIZE(tmu1_resources),
+	.archdata = {
+		.hwblk_id = HWBLK_TMU0,
+	},
 };
 
 static struct sh_timer_config tmu2_platform_data = {
@@ -225,6 +244,9 @@ static struct platform_device tmu2_device = {
 	},
 	.resource	= tmu2_resources,
 	.num_resources	= ARRAY_SIZE(tmu2_resources),
+	.archdata = {
+		.hwblk_id = HWBLK_TMU0,
+	},
 };
 
 static struct sh_timer_config tmu3_platform_data = {
@@ -255,6 +277,9 @@ static struct platform_device tmu3_device = {
 	},
 	.resource	= tmu3_resources,
 	.num_resources	= ARRAY_SIZE(tmu3_resources),
+	.archdata = {
+		.hwblk_id = HWBLK_TMU1,
+	},
 };
 
 static struct sh_timer_config tmu4_platform_data = {
@@ -285,6 +310,9 @@ static struct platform_device tmu4_device = {
 	},
 	.resource	= tmu4_resources,
 	.num_resources	= ARRAY_SIZE(tmu4_resources),
+	.archdata = {
+		.hwblk_id = HWBLK_TMU1,
+	},
 };
 
 static struct sh_timer_config tmu5_platform_data = {
@@ -315,6 +343,9 @@ static struct platform_device tmu5_device = {
 	},
 	.resource	= tmu5_resources,
 	.num_resources	= ARRAY_SIZE(tmu5_resources),
+	.archdata = {
+		.hwblk_id = HWBLK_TMU1,
+	},
 };
 
 static struct plat_sci_port sci_platform_data[] = {
@@ -395,10 +426,13 @@ static struct platform_device rtc_device = {
 	.id		= -1,
 	.num_resources	= ARRAY_SIZE(rtc_resources),
 	.resource	= rtc_resources,
+	.archdata = {
+		.hwblk_id = HWBLK_RTC,
+	},
 };
 
 static struct r8a66597_platdata r8a66597_data = {
-	/* This set zero to all members */
+	.on_chip = 1,
 };
 
 static struct resource sh7723_usb_host_resources[] = {
@@ -424,6 +458,9 @@ static struct platform_device sh7723_usb_host_device = {
 	},
 	.num_resources	= ARRAY_SIZE(sh7723_usb_host_resources),
 	.resource	= sh7723_usb_host_resources,
+	.archdata = {
+		.hwblk_id = HWBLK_USB,
+	},
 };
 
 static struct resource iic_resources[] = {
@@ -445,6 +482,9 @@ static struct platform_device iic_device = {
 	.id             = 0, /* "i2c0" clock */
 	.num_resources  = ARRAY_SIZE(iic_resources),
 	.resource       = iic_resources,
+	.archdata = {
+		.hwblk_id = HWBLK_IIC,
+	},
 };
 
 static struct platform_device *sh7723_devices[] __initdata = {
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
index a04edaab9a29..f3851fd757ec 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
@@ -22,6 +22,7 @@
 #include <linux/io.h>
 #include <asm/clock.h>
 #include <asm/mmzone.h>
+#include <cpu/sh7724.h>
 
 /* Serial */
 static struct plat_sci_port sci_platform_data[] = {
@@ -103,6 +104,9 @@ static struct platform_device rtc_device = {
 	.id		= -1,
 	.num_resources	= ARRAY_SIZE(rtc_resources),
 	.resource	= rtc_resources,
+	.archdata = {
+		.hwblk_id = HWBLK_RTC,
+	},
 };
 
 /* I2C0 */
@@ -125,6 +129,9 @@ static struct platform_device iic0_device = {
 	.id             = 0, /* "i2c0" clock */
 	.num_resources  = ARRAY_SIZE(iic0_resources),
 	.resource       = iic0_resources,
+	.archdata = {
+		.hwblk_id = HWBLK_IIC0,
+	},
 };
 
 /* I2C1 */
@@ -147,6 +154,9 @@ static struct platform_device iic1_device = {
 	.id             = 1, /* "i2c1" clock */
 	.num_resources  = ARRAY_SIZE(iic1_resources),
 	.resource       = iic1_resources,
+	.archdata = {
+		.hwblk_id = HWBLK_IIC1,
+	},
 };
 
 /* VPU */
@@ -176,6 +186,9 @@ static struct platform_device vpu_device = {
 	},
 	.resource	= vpu_resources,
 	.num_resources	= ARRAY_SIZE(vpu_resources),
+	.archdata = {
+		.hwblk_id = HWBLK_VPU,
+	},
 };
 
 /* VEU0 */
@@ -205,6 +218,9 @@ static struct platform_device veu0_device = {
 	},
 	.resource	= veu0_resources,
 	.num_resources	= ARRAY_SIZE(veu0_resources),
+	.archdata = {
+		.hwblk_id = HWBLK_VEU0,
+	},
 };
 
 /* VEU1 */
@@ -234,6 +250,9 @@ static struct platform_device veu1_device = {
 	},
 	.resource	= veu1_resources,
 	.num_resources	= ARRAY_SIZE(veu1_resources),
+	.archdata = {
+		.hwblk_id = HWBLK_VEU1,
+	},
 };
 
 static struct sh_timer_config cmt_platform_data = {
@@ -266,6 +285,9 @@ static struct platform_device cmt_device = {
 	},
 	.resource	= cmt_resources,
 	.num_resources	= ARRAY_SIZE(cmt_resources),
+	.archdata = {
+		.hwblk_id = HWBLK_CMT,
+	},
 };
 
 static struct sh_timer_config tmu0_platform_data = {
@@ -297,6 +319,9 @@ static struct platform_device tmu0_device = {
 	},
 	.resource	= tmu0_resources,
 	.num_resources	= ARRAY_SIZE(tmu0_resources),
+	.archdata = {
+		.hwblk_id = HWBLK_TMU0,
+	},
 };
 
 static struct sh_timer_config tmu1_platform_data = {
@@ -328,6 +353,9 @@ static struct platform_device tmu1_device = {
 	},
 	.resource	= tmu1_resources,
 	.num_resources	= ARRAY_SIZE(tmu1_resources),
+	.archdata = {
+		.hwblk_id = HWBLK_TMU0,
+	},
 };
 
 static struct sh_timer_config tmu2_platform_data = {
@@ -358,6 +386,9 @@ static struct platform_device tmu2_device = {
 	},
 	.resource	= tmu2_resources,
 	.num_resources	= ARRAY_SIZE(tmu2_resources),
+	.archdata = {
+		.hwblk_id = HWBLK_TMU0,
+	},
 };
 
 
@@ -389,6 +420,9 @@ static struct platform_device tmu3_device = {
 	},
 	.resource	= tmu3_resources,
 	.num_resources	= ARRAY_SIZE(tmu3_resources),
+	.archdata = {
+		.hwblk_id = HWBLK_TMU1,
+	},
 };
 
 static struct sh_timer_config tmu4_platform_data = {
@@ -419,6 +453,9 @@ static struct platform_device tmu4_device = {
 	},
 	.resource	= tmu4_resources,
 	.num_resources	= ARRAY_SIZE(tmu4_resources),
+	.archdata = {
+		.hwblk_id = HWBLK_TMU1,
+	},
 };
 
 static struct sh_timer_config tmu5_platform_data = {
@@ -449,6 +486,9 @@ static struct platform_device tmu5_device = {
 	},
 	.resource	= tmu5_resources,
 	.num_resources	= ARRAY_SIZE(tmu5_resources),
+	.archdata = {
+		.hwblk_id = HWBLK_TMU1,
+	},
 };
 
 /* JPU */
@@ -478,6 +518,9 @@ static struct platform_device jpu_device = {
 	},
 	.resource	= jpu_resources,
 	.num_resources	= ARRAY_SIZE(jpu_resources),
+	.archdata = {
+		.hwblk_id = HWBLK_JPU,
+	},
 };
 
 static struct platform_device *sh7724_devices[] __initdata = {
diff --git a/arch/sh/kernel/cpu/shmobile/Makefile b/arch/sh/kernel/cpu/shmobile/Makefile
index 08bfa7c7db29..e8a5111e848a 100644
--- a/arch/sh/kernel/cpu/shmobile/Makefile
+++ b/arch/sh/kernel/cpu/shmobile/Makefile
@@ -4,3 +4,4 @@
 
 # Power Management & Sleep mode
 obj-$(CONFIG_PM)	+= pm.o sleep.o
+obj-$(CONFIG_CPU_IDLE)	+= cpuidle.o
diff --git a/arch/sh/kernel/cpu/shmobile/cpuidle.c b/arch/sh/kernel/cpu/shmobile/cpuidle.c
new file mode 100644
index 000000000000..4afdd975cc66
--- /dev/null
+++ b/arch/sh/kernel/cpu/shmobile/cpuidle.c
@@ -0,0 +1,102 @@
+/*
+ * arch/sh/kernel/cpu/shmobile/cpuidle.c
+ *
+ * Cpuidle support code for SuperH Mobile
+ *
+ *  Copyright (C) 2009 Magnus Damm
+ *
+ * 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/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/suspend.h>
+#include <linux/cpuidle.h>
+#include <asm/suspend.h>
+#include <asm/uaccess.h>
+#include <asm/hwblk.h>
+
+static unsigned long cpuidle_mode[] = {
+	SUSP_SH_SLEEP, /* regular sleep mode */
+	SUSP_SH_SLEEP | SUSP_SH_SF, /* sleep mode + self refresh */
+};
+
+static int cpuidle_sleep_enter(struct cpuidle_device *dev,
+			       struct cpuidle_state *state)
+{
+	unsigned long allowed_mode = arch_hwblk_sleep_mode();
+	ktime_t before, after;
+	int requested_state = state - &dev->states[0];
+	int allowed_state;
+	int k;
+
+	/* convert allowed mode to allowed state */
+	for (k = ARRAY_SIZE(cpuidle_mode) - 1; k > 0; k--)
+		if (cpuidle_mode[k] == allowed_mode)
+			break;
+
+	allowed_state = k;
+
+	/* take the following into account for sleep mode selection:
+	 * - allowed_state: best mode allowed by hardware (clock deps)
+	 * - requested_state: best mode allowed by software (latencies)
+	 */
+	k = min_t(int, allowed_state, requested_state);
+
+	dev->last_state = &dev->states[k];
+	before = ktime_get();
+	sh_mobile_call_standby(cpuidle_mode[k]);
+	after = ktime_get();
+	return ktime_to_ns(ktime_sub(after, before)) >> 10;
+}
+
+static struct cpuidle_device cpuidle_dev;
+static struct cpuidle_driver cpuidle_driver = {
+	.name =		"sh_idle",
+	.owner =	THIS_MODULE,
+};
+
+void sh_mobile_setup_cpuidle(void)
+{
+	struct cpuidle_device *dev = &cpuidle_dev;
+	struct cpuidle_state *state;
+	int i;
+
+	cpuidle_register_driver(&cpuidle_driver);
+
+	for (i = 0; i < CPUIDLE_STATE_MAX; i++) {
+		dev->states[i].name[0] = '\0';
+		dev->states[i].desc[0] = '\0';
+	}
+
+	i = CPUIDLE_DRIVER_STATE_START;
+
+	state = &dev->states[i++];
+	snprintf(state->name, CPUIDLE_NAME_LEN, "C0");
+	strncpy(state->desc, "SuperH Sleep Mode", CPUIDLE_DESC_LEN);
+	state->exit_latency = 1;
+	state->target_residency = 1 * 2;
+	state->power_usage = 3;
+	state->flags = 0;
+	state->flags |= CPUIDLE_FLAG_SHALLOW;
+	state->flags |= CPUIDLE_FLAG_TIME_VALID;
+	state->enter = cpuidle_sleep_enter;
+
+	dev->safe_state = state;
+
+	state = &dev->states[i++];
+	snprintf(state->name, CPUIDLE_NAME_LEN, "C1");
+	strncpy(state->desc, "SuperH Sleep Mode [SF]", CPUIDLE_DESC_LEN);
+	state->exit_latency = 100;
+	state->target_residency = 1 * 2;
+	state->power_usage = 1;
+	state->flags = 0;
+	state->flags |= CPUIDLE_FLAG_TIME_VALID;
+	state->enter = cpuidle_sleep_enter;
+
+	dev->state_count = i;
+
+	cpuidle_register_device(dev);
+}
diff --git a/arch/sh/kernel/cpu/shmobile/pm.c b/arch/sh/kernel/cpu/shmobile/pm.c
index 8c067adf6830..de078d24ce56 100644
--- a/arch/sh/kernel/cpu/shmobile/pm.c
+++ b/arch/sh/kernel/cpu/shmobile/pm.c
@@ -1,5 +1,5 @@
 /*
- * arch/sh/kernel/cpu/sh4a/pm-sh_mobile.c
+ * arch/sh/kernel/cpu/shmobile/pm.c
  *
  * Power management support code for SuperH Mobile
  *
@@ -32,20 +32,17 @@
  *
  * R-standby mode is unsupported, but will be added in the future
  * U-standby mode is low priority since it needs bootloader hacks
- *
- * All modes should be tied in with cpuidle. But before that can
- * happen we need to keep track of enabled hardware blocks so we
- * can avoid entering sleep modes that stop clocks to hardware
- * blocks that are in use even though the cpu core is idle.
  */
 
+#define ILRAM_BASE 0xe5200000
+
 extern const unsigned char sh_mobile_standby[];
 extern const unsigned int sh_mobile_standby_size;
 
-static void sh_mobile_call_standby(unsigned long mode)
+void sh_mobile_call_standby(unsigned long mode)
 {
 	extern void *vbr_base;
-	void *onchip_mem = (void *)0xe5200000; /* ILRAM */
+	void *onchip_mem = (void *)ILRAM_BASE;
 	void (*standby_onchip_mem)(unsigned long) = onchip_mem;
 
 	/* Note: Wake up from sleep may generate exceptions!
@@ -55,11 +52,6 @@ static void sh_mobile_call_standby(unsigned long mode)
 	if (mode & SUSP_SH_SF)
 		asm volatile("ldc %0, vbr" : : "r" (onchip_mem) : "memory");
 
-	/* Copy the assembly snippet to the otherwise ununsed ILRAM */
-	memcpy(onchip_mem, sh_mobile_standby, sh_mobile_standby_size);
-	wmb();
-	ctrl_barrier();
-
 	/* Let assembly snippet in on-chip memory handle the rest */
 	standby_onchip_mem(mode);
 
@@ -85,7 +77,15 @@ static struct platform_suspend_ops sh_pm_ops = {
 
 static int __init sh_pm_init(void)
 {
+	void *onchip_mem = (void *)ILRAM_BASE;
+
+	/* Copy the assembly snippet to the otherwise ununsed ILRAM */
+	memcpy(onchip_mem, sh_mobile_standby, sh_mobile_standby_size);
+	wmb();
+	ctrl_barrier();
+
 	suspend_set_ops(&sh_pm_ops);
+	sh_mobile_setup_cpuidle();
 	return 0;
 }
 
diff --git a/arch/sh/kernel/dumpstack.c b/arch/sh/kernel/dumpstack.c
new file mode 100644
index 000000000000..6f5ad1513409
--- /dev/null
+++ b/arch/sh/kernel/dumpstack.c
@@ -0,0 +1,123 @@
+/*
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *  Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
+ *  Copyright (C) 2009  Matt Fleming
+ */
+#include <linux/kallsyms.h>
+#include <linux/ftrace.h>
+#include <linux/debug_locks.h>
+#include <asm/unwinder.h>
+#include <asm/stacktrace.h>
+
+void printk_address(unsigned long address, int reliable)
+{
+	printk(" [<%p>] %s%pS\n", (void *) address,
+			reliable ? "" : "? ", (void *) address);
+}
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+static void
+print_ftrace_graph_addr(unsigned long addr, void *data,
+			const struct stacktrace_ops *ops,
+			struct thread_info *tinfo, int *graph)
+{
+	struct task_struct *task = tinfo->task;
+	unsigned long ret_addr;
+	int index = task->curr_ret_stack;
+
+	if (addr != (unsigned long)return_to_handler)
+		return;
+
+	if (!task->ret_stack || index < *graph)
+		return;
+
+	index -= *graph;
+	ret_addr = task->ret_stack[index].ret;
+
+	ops->address(data, ret_addr, 1);
+
+	(*graph)++;
+}
+#else
+static inline void
+print_ftrace_graph_addr(unsigned long addr, void *data,
+			const struct stacktrace_ops *ops,
+			struct thread_info *tinfo, int *graph)
+{ }
+#endif
+
+void
+stack_reader_dump(struct task_struct *task, struct pt_regs *regs,
+		  unsigned long *sp, const struct stacktrace_ops *ops,
+		  void *data)
+{
+	struct thread_info *context;
+	int graph = 0;
+
+	context = (struct thread_info *)
+		((unsigned long)sp & (~(THREAD_SIZE - 1)));
+
+	while (!kstack_end(sp)) {
+		unsigned long addr = *sp++;
+
+		if (__kernel_text_address(addr)) {
+			ops->address(data, addr, 1);
+
+			print_ftrace_graph_addr(addr, data, ops,
+						context, &graph);
+		}
+	}
+}
+
+static void
+print_trace_warning_symbol(void *data, char *msg, unsigned long symbol)
+{
+	printk(data);
+	print_symbol(msg, symbol);
+	printk("\n");
+}
+
+static void print_trace_warning(void *data, char *msg)
+{
+	printk("%s%s\n", (char *)data, msg);
+}
+
+static int print_trace_stack(void *data, char *name)
+{
+	printk("%s <%s> ", (char *)data, name);
+	return 0;
+}
+
+/*
+ * Print one address/symbol entries per line.
+ */
+static void print_trace_address(void *data, unsigned long addr, int reliable)
+{
+	printk(data);
+	printk_address(addr, reliable);
+}
+
+static const struct stacktrace_ops print_trace_ops = {
+	.warning = print_trace_warning,
+	.warning_symbol = print_trace_warning_symbol,
+	.stack = print_trace_stack,
+	.address = print_trace_address,
+};
+
+void show_trace(struct task_struct *tsk, unsigned long *sp,
+		struct pt_regs *regs)
+{
+	if (regs && user_mode(regs))
+		return;
+
+	printk("\nCall trace:\n");
+
+	unwind_stack(tsk, regs, sp, &print_trace_ops, "");
+
+	printk("\n");
+
+	if (!tsk)
+		tsk = current;
+
+	debug_show_held_locks(tsk);
+}
diff --git a/arch/sh/kernel/dwarf.c b/arch/sh/kernel/dwarf.c
new file mode 100644
index 000000000000..c6c5764a8ab1
--- /dev/null
+++ b/arch/sh/kernel/dwarf.c
@@ -0,0 +1,902 @@
+/*
+ * Copyright (C) 2009 Matt Fleming <matt@console-pimps.org>
+ *
+ * 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.
+ *
+ * This is an implementation of a DWARF unwinder. Its main purpose is
+ * for generating stacktrace information. Based on the DWARF 3
+ * specification from http://www.dwarfstd.org.
+ *
+ * TODO:
+ *	- DWARF64 doesn't work.
+ */
+
+/* #define DEBUG */
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <asm/dwarf.h>
+#include <asm/unwinder.h>
+#include <asm/sections.h>
+#include <asm/unaligned.h>
+#include <asm/dwarf.h>
+#include <asm/stacktrace.h>
+
+static LIST_HEAD(dwarf_cie_list);
+DEFINE_SPINLOCK(dwarf_cie_lock);
+
+static LIST_HEAD(dwarf_fde_list);
+DEFINE_SPINLOCK(dwarf_fde_lock);
+
+static struct dwarf_cie *cached_cie;
+
+/*
+ * Figure out whether we need to allocate some dwarf registers. If dwarf
+ * registers have already been allocated then we may need to realloc
+ * them. "reg" is a register number that we need to be able to access
+ * after this call.
+ *
+ * Register numbers start at zero, therefore we need to allocate space
+ * for "reg" + 1 registers.
+ */
+static void dwarf_frame_alloc_regs(struct dwarf_frame *frame,
+				   unsigned int reg)
+{
+	struct dwarf_reg *regs;
+	unsigned int num_regs = reg + 1;
+	size_t new_size;
+	size_t old_size;
+
+	new_size = num_regs * sizeof(*regs);
+	old_size = frame->num_regs * sizeof(*regs);
+
+	/* Fast path: don't allocate any regs if we've already got enough. */
+	if (frame->num_regs >= num_regs)
+		return;
+
+	regs = kzalloc(new_size, GFP_ATOMIC);
+	if (!regs) {
+		printk(KERN_WARNING "Unable to allocate DWARF registers\n");
+		/*
+		 * Let's just bomb hard here, we have no way to
+		 * gracefully recover.
+		 */
+		BUG();
+	}
+
+	if (frame->regs) {
+		memcpy(regs, frame->regs, old_size);
+		kfree(frame->regs);
+	}
+
+	frame->regs = regs;
+	frame->num_regs = num_regs;
+}
+
+/**
+ *	dwarf_read_addr - read dwarf data
+ *	@src: source address of data
+ *	@dst: destination address to store the data to
+ *
+ *	Read 'n' bytes from @src, where 'n' is the size of an address on
+ *	the native machine. We return the number of bytes read, which
+ *	should always be 'n'. We also have to be careful when reading
+ *	from @src and writing to @dst, because they can be arbitrarily
+ *	aligned. Return 'n' - the number of bytes read.
+ */
+static inline int dwarf_read_addr(unsigned long *src, unsigned long *dst)
+{
+	u32 val = get_unaligned(src);
+	put_unaligned(val, dst);
+	return sizeof(unsigned long *);
+}
+
+/**
+ *	dwarf_read_uleb128 - read unsigned LEB128 data
+ *	@addr: the address where the ULEB128 data is stored
+ *	@ret: address to store the result
+ *
+ *	Decode an unsigned LEB128 encoded datum. The algorithm is taken
+ *	from Appendix C of the DWARF 3 spec. For information on the
+ *	encodings refer to section "7.6 - Variable Length Data". Return
+ *	the number of bytes read.
+ */
+static inline unsigned long dwarf_read_uleb128(char *addr, unsigned int *ret)
+{
+	unsigned int result;
+	unsigned char byte;
+	int shift, count;
+
+	result = 0;
+	shift = 0;
+	count = 0;
+
+	while (1) {
+		byte = __raw_readb(addr);
+		addr++;
+		count++;
+
+		result |= (byte & 0x7f) << shift;
+		shift += 7;
+
+		if (!(byte & 0x80))
+			break;
+	}
+
+	*ret = result;
+
+	return count;
+}
+
+/**
+ *	dwarf_read_leb128 - read signed LEB128 data
+ *	@addr: the address of the LEB128 encoded data
+ *	@ret: address to store the result
+ *
+ *	Decode signed LEB128 data. The algorithm is taken from Appendix
+ *	C of the DWARF 3 spec. Return the number of bytes read.
+ */
+static inline unsigned long dwarf_read_leb128(char *addr, int *ret)
+{
+	unsigned char byte;
+	int result, shift;
+	int num_bits;
+	int count;
+
+	result = 0;
+	shift = 0;
+	count = 0;
+
+	while (1) {
+		byte = __raw_readb(addr);
+		addr++;
+		result |= (byte & 0x7f) << shift;
+		shift += 7;
+		count++;
+
+		if (!(byte & 0x80))
+			break;
+	}
+
+	/* The number of bits in a signed integer. */
+	num_bits = 8 * sizeof(result);
+
+	if ((shift < num_bits) && (byte & 0x40))
+		result |= (-1 << shift);
+
+	*ret = result;
+
+	return count;
+}
+
+/**
+ *	dwarf_read_encoded_value - return the decoded value at @addr
+ *	@addr: the address of the encoded value
+ *	@val: where to write the decoded value
+ *	@encoding: the encoding with which we can decode @addr
+ *
+ *	GCC emits encoded address in the .eh_frame FDE entries. Decode
+ *	the value at @addr using @encoding. The decoded value is written
+ *	to @val and the number of bytes read is returned.
+ */
+static int dwarf_read_encoded_value(char *addr, unsigned long *val,
+				    char encoding)
+{
+	unsigned long decoded_addr = 0;
+	int count = 0;
+
+	switch (encoding & 0x70) {
+	case DW_EH_PE_absptr:
+		break;
+	case DW_EH_PE_pcrel:
+		decoded_addr = (unsigned long)addr;
+		break;
+	default:
+		pr_debug("encoding=0x%x\n", (encoding & 0x70));
+		BUG();
+	}
+
+	if ((encoding & 0x07) == 0x00)
+		encoding |= DW_EH_PE_udata4;
+
+	switch (encoding & 0x0f) {
+	case DW_EH_PE_sdata4:
+	case DW_EH_PE_udata4:
+		count += 4;
+		decoded_addr += get_unaligned((u32 *)addr);
+		__raw_writel(decoded_addr, val);
+		break;
+	default:
+		pr_debug("encoding=0x%x\n", encoding);
+		BUG();
+	}
+
+	return count;
+}
+
+/**
+ *	dwarf_entry_len - return the length of an FDE or CIE
+ *	@addr: the address of the entry
+ *	@len: the length of the entry
+ *
+ *	Read the initial_length field of the entry and store the size of
+ *	the entry in @len. We return the number of bytes read. Return a
+ *	count of 0 on error.
+ */
+static inline int dwarf_entry_len(char *addr, unsigned long *len)
+{
+	u32 initial_len;
+	int count;
+
+	initial_len = get_unaligned((u32 *)addr);
+	count = 4;
+
+	/*
+	 * An initial length field value in the range DW_LEN_EXT_LO -
+	 * DW_LEN_EXT_HI indicates an extension, and should not be
+	 * interpreted as a length. The only extension that we currently
+	 * understand is the use of DWARF64 addresses.
+	 */
+	if (initial_len >= DW_EXT_LO && initial_len <= DW_EXT_HI) {
+		/*
+		 * The 64-bit length field immediately follows the
+		 * compulsory 32-bit length field.
+		 */
+		if (initial_len == DW_EXT_DWARF64) {
+			*len = get_unaligned((u64 *)addr + 4);
+			count = 12;
+		} else {
+			printk(KERN_WARNING "Unknown DWARF extension\n");
+			count = 0;
+		}
+	} else
+		*len = initial_len;
+
+	return count;
+}
+
+/**
+ *	dwarf_lookup_cie - locate the cie
+ *	@cie_ptr: pointer to help with lookup
+ */
+static struct dwarf_cie *dwarf_lookup_cie(unsigned long cie_ptr)
+{
+	struct dwarf_cie *cie, *n;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dwarf_cie_lock, flags);
+
+	/*
+	 * We've cached the last CIE we looked up because chances are
+	 * that the FDE wants this CIE.
+	 */
+	if (cached_cie && cached_cie->cie_pointer == cie_ptr) {
+		cie = cached_cie;
+		goto out;
+	}
+
+	list_for_each_entry_safe(cie, n, &dwarf_cie_list, link) {
+		if (cie->cie_pointer == cie_ptr) {
+			cached_cie = cie;
+			break;
+		}
+	}
+
+	/* Couldn't find the entry in the list. */
+	if (&cie->link == &dwarf_cie_list)
+		cie = NULL;
+out:
+	spin_unlock_irqrestore(&dwarf_cie_lock, flags);
+	return cie;
+}
+
+/**
+ *	dwarf_lookup_fde - locate the FDE that covers pc
+ *	@pc: the program counter
+ */
+struct dwarf_fde *dwarf_lookup_fde(unsigned long pc)
+{
+	unsigned long flags;
+	struct dwarf_fde *fde, *n;
+
+	spin_lock_irqsave(&dwarf_fde_lock, flags);
+	list_for_each_entry_safe(fde, n, &dwarf_fde_list, link) {
+		unsigned long start, end;
+
+		start = fde->initial_location;
+		end = fde->initial_location + fde->address_range;
+
+		if (pc >= start && pc < end)
+			break;
+	}
+
+	/* Couldn't find the entry in the list. */
+	if (&fde->link == &dwarf_fde_list)
+		fde = NULL;
+
+	spin_unlock_irqrestore(&dwarf_fde_lock, flags);
+
+	return fde;
+}
+
+/**
+ *	dwarf_cfa_execute_insns - execute instructions to calculate a CFA
+ *	@insn_start: address of the first instruction
+ *	@insn_end: address of the last instruction
+ *	@cie: the CIE for this function
+ *	@fde: the FDE for this function
+ *	@frame: the instructions calculate the CFA for this frame
+ *	@pc: the program counter of the address we're interested in
+ *	@define_ra: keep executing insns until the return addr reg is defined?
+ *
+ *	Execute the Call Frame instruction sequence starting at
+ *	@insn_start and ending at @insn_end. The instructions describe
+ *	how to calculate the Canonical Frame Address of a stackframe.
+ *	Store the results in @frame.
+ */
+static int dwarf_cfa_execute_insns(unsigned char *insn_start,
+				   unsigned char *insn_end,
+				   struct dwarf_cie *cie,
+				   struct dwarf_fde *fde,
+				   struct dwarf_frame *frame,
+				   unsigned long pc,
+				   bool define_ra)
+{
+	unsigned char insn;
+	unsigned char *current_insn;
+	unsigned int count, delta, reg, expr_len, offset;
+	bool seen_ra_reg;
+
+	current_insn = insn_start;
+
+	/*
+	 * If we're executing instructions for the dwarf_unwind_stack()
+	 * FDE we need to keep executing instructions until the value of
+	 * DWARF_ARCH_RA_REG is defined. See the comment in
+	 * dwarf_unwind_stack() for more details.
+	 */
+	if (define_ra)
+		seen_ra_reg = false;
+	else
+		seen_ra_reg = true;
+
+	while (current_insn < insn_end && (frame->pc <= pc || !seen_ra_reg) ) {
+		insn = __raw_readb(current_insn++);
+
+		if (!seen_ra_reg) {
+			if (frame->num_regs >= DWARF_ARCH_RA_REG &&
+			    frame->regs[DWARF_ARCH_RA_REG].flags)
+				seen_ra_reg = true;
+		}
+
+		/*
+		 * Firstly, handle the opcodes that embed their operands
+		 * in the instructions.
+		 */
+		switch (DW_CFA_opcode(insn)) {
+		case DW_CFA_advance_loc:
+			delta = DW_CFA_operand(insn);
+			delta *= cie->code_alignment_factor;
+			frame->pc += delta;
+			continue;
+			/* NOTREACHED */
+		case DW_CFA_offset:
+			reg = DW_CFA_operand(insn);
+			count = dwarf_read_uleb128(current_insn, &offset);
+			current_insn += count;
+			offset *= cie->data_alignment_factor;
+			dwarf_frame_alloc_regs(frame, reg);
+			frame->regs[reg].addr = offset;
+			frame->regs[reg].flags |= DWARF_REG_OFFSET;
+			continue;
+			/* NOTREACHED */
+		case DW_CFA_restore:
+			reg = DW_CFA_operand(insn);
+			continue;
+			/* NOTREACHED */
+		}
+
+		/*
+		 * Secondly, handle the opcodes that don't embed their
+		 * operands in the instruction.
+		 */
+		switch (insn) {
+		case DW_CFA_nop:
+			continue;
+		case DW_CFA_advance_loc1:
+			delta = *current_insn++;
+			frame->pc += delta * cie->code_alignment_factor;
+			break;
+		case DW_CFA_advance_loc2:
+			delta = get_unaligned((u16 *)current_insn);
+			current_insn += 2;
+			frame->pc += delta * cie->code_alignment_factor;
+			break;
+		case DW_CFA_advance_loc4:
+			delta = get_unaligned((u32 *)current_insn);
+			current_insn += 4;
+			frame->pc += delta * cie->code_alignment_factor;
+			break;
+		case DW_CFA_offset_extended:
+			count = dwarf_read_uleb128(current_insn, &reg);
+			current_insn += count;
+			count = dwarf_read_uleb128(current_insn, &offset);
+			current_insn += count;
+			offset *= cie->data_alignment_factor;
+			break;
+		case DW_CFA_restore_extended:
+			count = dwarf_read_uleb128(current_insn, &reg);
+			current_insn += count;
+			break;
+		case DW_CFA_undefined:
+			count = dwarf_read_uleb128(current_insn, &reg);
+			current_insn += count;
+			break;
+		case DW_CFA_def_cfa:
+			count = dwarf_read_uleb128(current_insn,
+						   &frame->cfa_register);
+			current_insn += count;
+			count = dwarf_read_uleb128(current_insn,
+						   &frame->cfa_offset);
+			current_insn += count;
+
+			frame->flags |= DWARF_FRAME_CFA_REG_OFFSET;
+			break;
+		case DW_CFA_def_cfa_register:
+			count = dwarf_read_uleb128(current_insn,
+						   &frame->cfa_register);
+			current_insn += count;
+			frame->cfa_offset = 0;
+			frame->flags |= DWARF_FRAME_CFA_REG_OFFSET;
+			break;
+		case DW_CFA_def_cfa_offset:
+			count = dwarf_read_uleb128(current_insn, &offset);
+			current_insn += count;
+			frame->cfa_offset = offset;
+			break;
+		case DW_CFA_def_cfa_expression:
+			count = dwarf_read_uleb128(current_insn, &expr_len);
+			current_insn += count;
+
+			frame->cfa_expr = current_insn;
+			frame->cfa_expr_len = expr_len;
+			current_insn += expr_len;
+
+			frame->flags |= DWARF_FRAME_CFA_REG_EXP;
+			break;
+		case DW_CFA_offset_extended_sf:
+			count = dwarf_read_uleb128(current_insn, &reg);
+			current_insn += count;
+			count = dwarf_read_leb128(current_insn, &offset);
+			current_insn += count;
+			offset *= cie->data_alignment_factor;
+			dwarf_frame_alloc_regs(frame, reg);
+			frame->regs[reg].flags |= DWARF_REG_OFFSET;
+			frame->regs[reg].addr = offset;
+			break;
+		case DW_CFA_val_offset:
+			count = dwarf_read_uleb128(current_insn, &reg);
+			current_insn += count;
+			count = dwarf_read_leb128(current_insn, &offset);
+			offset *= cie->data_alignment_factor;
+			frame->regs[reg].flags |= DWARF_REG_OFFSET;
+			frame->regs[reg].addr = offset;
+			break;
+		default:
+			pr_debug("unhandled DWARF instruction 0x%x\n", insn);
+			break;
+		}
+	}
+
+	return 0;
+}
+
+/**
+ *	dwarf_unwind_stack - recursively unwind the stack
+ *	@pc: address of the function to unwind
+ *	@prev: struct dwarf_frame of the previous stackframe on the callstack
+ *
+ *	Return a struct dwarf_frame representing the most recent frame
+ *	on the callstack. Each of the lower (older) stack frames are
+ *	linked via the "prev" member.
+ */
+struct dwarf_frame *dwarf_unwind_stack(unsigned long pc,
+				       struct dwarf_frame *prev)
+{
+	struct dwarf_frame *frame;
+	struct dwarf_cie *cie;
+	struct dwarf_fde *fde;
+	unsigned long addr;
+	int i, offset;
+	bool define_ra = false;
+
+	/*
+	 * If this is the first invocation of this recursive function we
+	 * need get the contents of a physical register to get the CFA
+	 * in order to begin the virtual unwinding of the stack.
+	 *
+	 * Setting "define_ra" to true indictates that we want
+	 * dwarf_cfa_execute_insns() to continue executing instructions
+	 * until we know how to calculate the value of DWARF_ARCH_RA_REG
+	 * (which we need in order to kick off the whole unwinding
+	 * process).
+	 *
+	 * NOTE: the return address is guaranteed to be setup by the
+	 * time this function makes its first function call.
+	 */
+	if (!pc && !prev) {
+		pc = (unsigned long)&dwarf_unwind_stack;
+		define_ra = true;
+	}
+
+	frame = kzalloc(sizeof(*frame), GFP_ATOMIC);
+	if (!frame)
+		return NULL;
+
+	frame->prev = prev;
+
+	fde = dwarf_lookup_fde(pc);
+	if (!fde) {
+		/*
+		 * This is our normal exit path - the one that stops the
+		 * recursion. There's two reasons why we might exit
+		 * here,
+		 *
+		 *	a) pc has no asscociated DWARF frame info and so
+		 *	we don't know how to unwind this frame. This is
+		 *	usually the case when we're trying to unwind a
+		 *	frame that was called from some assembly code
+		 *	that has no DWARF info, e.g. syscalls.
+		 *
+		 *	b) the DEBUG info for pc is bogus. There's
+		 *	really no way to distinguish this case from the
+		 *	case above, which sucks because we could print a
+		 *	warning here.
+		 */
+		return NULL;
+	}
+
+	cie = dwarf_lookup_cie(fde->cie_pointer);
+
+	frame->pc = fde->initial_location;
+
+	/* CIE initial instructions */
+	dwarf_cfa_execute_insns(cie->initial_instructions,
+				cie->instructions_end, cie, fde,
+				frame, pc, false);
+
+	/* FDE instructions */
+	dwarf_cfa_execute_insns(fde->instructions, fde->end, cie,
+				fde, frame, pc, define_ra);
+
+	/* Calculate the CFA */
+	switch (frame->flags) {
+	case DWARF_FRAME_CFA_REG_OFFSET:
+		if (prev) {
+			BUG_ON(!prev->regs[frame->cfa_register].flags);
+
+			addr = prev->cfa;
+			addr += prev->regs[frame->cfa_register].addr;
+			frame->cfa = __raw_readl(addr);
+
+		} else {
+			/*
+			 * Again, this is the first invocation of this
+			 * recurisve function. We need to physically
+			 * read the contents of a register in order to
+			 * get the Canonical Frame Address for this
+			 * function.
+			 */
+			frame->cfa = dwarf_read_arch_reg(frame->cfa_register);
+		}
+
+		frame->cfa += frame->cfa_offset;
+		break;
+	default:
+		BUG();
+	}
+
+	/* If we haven't seen the return address reg, we're screwed. */
+	BUG_ON(!frame->regs[DWARF_ARCH_RA_REG].flags);
+
+	for (i = 0; i <= frame->num_regs; i++) {
+		struct dwarf_reg *reg = &frame->regs[i];
+
+		if (!reg->flags)
+			continue;
+
+		offset = reg->addr;
+		offset += frame->cfa;
+	}
+
+	addr = frame->cfa + frame->regs[DWARF_ARCH_RA_REG].addr;
+	frame->return_addr = __raw_readl(addr);
+
+	frame->next = dwarf_unwind_stack(frame->return_addr, frame);
+	return frame;
+}
+
+static int dwarf_parse_cie(void *entry, void *p, unsigned long len,
+			   unsigned char *end)
+{
+	struct dwarf_cie *cie;
+	unsigned long flags;
+	int count;
+
+	cie = kzalloc(sizeof(*cie), GFP_KERNEL);
+	if (!cie)
+		return -ENOMEM;
+
+	cie->length = len;
+
+	/*
+	 * Record the offset into the .eh_frame section
+	 * for this CIE. It allows this CIE to be
+	 * quickly and easily looked up from the
+	 * corresponding FDE.
+	 */
+	cie->cie_pointer = (unsigned long)entry;
+
+	cie->version = *(char *)p++;
+	BUG_ON(cie->version != 1);
+
+	cie->augmentation = p;
+	p += strlen(cie->augmentation) + 1;
+
+	count = dwarf_read_uleb128(p, &cie->code_alignment_factor);
+	p += count;
+
+	count = dwarf_read_leb128(p, &cie->data_alignment_factor);
+	p += count;
+
+	/*
+	 * Which column in the rule table contains the
+	 * return address?
+	 */
+	if (cie->version == 1) {
+		cie->return_address_reg = __raw_readb(p);
+		p++;
+	} else {
+		count = dwarf_read_uleb128(p, &cie->return_address_reg);
+		p += count;
+	}
+
+	if (cie->augmentation[0] == 'z') {
+		unsigned int length, count;
+		cie->flags |= DWARF_CIE_Z_AUGMENTATION;
+
+		count = dwarf_read_uleb128(p, &length);
+		p += count;
+
+		BUG_ON((unsigned char *)p > end);
+
+		cie->initial_instructions = p + length;
+		cie->augmentation++;
+	}
+
+	while (*cie->augmentation) {
+		/*
+		 * "L" indicates a byte showing how the
+		 * LSDA pointer is encoded. Skip it.
+		 */
+		if (*cie->augmentation == 'L') {
+			p++;
+			cie->augmentation++;
+		} else if (*cie->augmentation == 'R') {
+			/*
+			 * "R" indicates a byte showing
+			 * how FDE addresses are
+			 * encoded.
+			 */
+			cie->encoding = *(char *)p++;
+			cie->augmentation++;
+		} else if (*cie->augmentation == 'P') {
+			/*
+			 * "R" indicates a personality
+			 * routine in the CIE
+			 * augmentation.
+			 */
+			BUG();
+		} else if (*cie->augmentation == 'S') {
+			BUG();
+		} else {
+			/*
+			 * Unknown augmentation. Assume
+			 * 'z' augmentation.
+			 */
+			p = cie->initial_instructions;
+			BUG_ON(!p);
+			break;
+		}
+	}
+
+	cie->initial_instructions = p;
+	cie->instructions_end = end;
+
+	/* Add to list */
+	spin_lock_irqsave(&dwarf_cie_lock, flags);
+	list_add_tail(&cie->link, &dwarf_cie_list);
+	spin_unlock_irqrestore(&dwarf_cie_lock, flags);
+
+	return 0;
+}
+
+static int dwarf_parse_fde(void *entry, u32 entry_type,
+			   void *start, unsigned long len)
+{
+	struct dwarf_fde *fde;
+	struct dwarf_cie *cie;
+	unsigned long flags;
+	int count;
+	void *p = start;
+
+	fde = kzalloc(sizeof(*fde), GFP_KERNEL);
+	if (!fde)
+		return -ENOMEM;
+
+	fde->length = len;
+
+	/*
+	 * In a .eh_frame section the CIE pointer is the
+	 * delta between the address within the FDE
+	 */
+	fde->cie_pointer = (unsigned long)(p - entry_type - 4);
+
+	cie = dwarf_lookup_cie(fde->cie_pointer);
+	fde->cie = cie;
+
+	if (cie->encoding)
+		count = dwarf_read_encoded_value(p, &fde->initial_location,
+						 cie->encoding);
+	else
+		count = dwarf_read_addr(p, &fde->initial_location);
+
+	p += count;
+
+	if (cie->encoding)
+		count = dwarf_read_encoded_value(p, &fde->address_range,
+						 cie->encoding & 0x0f);
+	else
+		count = dwarf_read_addr(p, &fde->address_range);
+
+	p += count;
+
+	if (fde->cie->flags & DWARF_CIE_Z_AUGMENTATION) {
+		unsigned int length;
+		count = dwarf_read_uleb128(p, &length);
+		p += count + length;
+	}
+
+	/* Call frame instructions. */
+	fde->instructions = p;
+	fde->end = start + len;
+
+	/* Add to list. */
+	spin_lock_irqsave(&dwarf_fde_lock, flags);
+	list_add_tail(&fde->link, &dwarf_fde_list);
+	spin_unlock_irqrestore(&dwarf_fde_lock, flags);
+
+	return 0;
+}
+
+static void dwarf_unwinder_dump(struct task_struct *task, struct pt_regs *regs,
+				unsigned long *sp,
+				const struct stacktrace_ops *ops, void *data)
+{
+	struct dwarf_frame *frame;
+
+	frame = dwarf_unwind_stack(0, NULL);
+
+	while (frame && frame->return_addr) {
+		ops->address(data, frame->return_addr, 1);
+		frame = frame->next;
+	}
+}
+
+static struct unwinder dwarf_unwinder = {
+	.name = "dwarf-unwinder",
+	.dump = dwarf_unwinder_dump,
+	.rating = 150,
+};
+
+static void dwarf_unwinder_cleanup(void)
+{
+	struct dwarf_cie *cie, *m;
+	struct dwarf_fde *fde, *n;
+	unsigned long flags;
+
+	/*
+	 * Deallocate all the memory allocated for the DWARF unwinder.
+	 * Traverse all the FDE/CIE lists and remove and free all the
+	 * memory associated with those data structures.
+	 */
+	spin_lock_irqsave(&dwarf_cie_lock, flags);
+	list_for_each_entry_safe(cie, m, &dwarf_cie_list, link)
+		kfree(cie);
+	spin_unlock_irqrestore(&dwarf_cie_lock, flags);
+
+	spin_lock_irqsave(&dwarf_fde_lock, flags);
+	list_for_each_entry_safe(fde, n, &dwarf_fde_list, link)
+		kfree(fde);
+	spin_unlock_irqrestore(&dwarf_fde_lock, flags);
+}
+
+/**
+ *	dwarf_unwinder_init - initialise the dwarf unwinder
+ *
+ *	Build the data structures describing the .dwarf_frame section to
+ *	make it easier to lookup CIE and FDE entries. Because the
+ *	.eh_frame section is packed as tightly as possible it is not
+ *	easy to lookup the FDE for a given PC, so we build a list of FDE
+ *	and CIE entries that make it easier.
+ */
+void dwarf_unwinder_init(void)
+{
+	u32 entry_type;
+	void *p, *entry;
+	int count, err;
+	unsigned long len;
+	unsigned int c_entries, f_entries;
+	unsigned char *end;
+	INIT_LIST_HEAD(&dwarf_cie_list);
+	INIT_LIST_HEAD(&dwarf_fde_list);
+
+	c_entries = 0;
+	f_entries = 0;
+	entry = &__start_eh_frame;
+
+	while ((char *)entry < __stop_eh_frame) {
+		p = entry;
+
+		count = dwarf_entry_len(p, &len);
+		if (count == 0) {
+			/*
+			 * We read a bogus length field value. There is
+			 * nothing we can do here apart from disabling
+			 * the DWARF unwinder. We can't even skip this
+			 * entry and move to the next one because 'len'
+			 * tells us where our next entry is.
+			 */
+			goto out;
+		} else
+			p += count;
+
+		/* initial length does not include itself */
+		end = p + len;
+
+		entry_type = get_unaligned((u32 *)p);
+		p += 4;
+
+		if (entry_type == DW_EH_FRAME_CIE) {
+			err = dwarf_parse_cie(entry, p, len, end);
+			if (err < 0)
+				goto out;
+			else
+				c_entries++;
+		} else {
+			err = dwarf_parse_fde(entry, entry_type, p, len);
+			if (err < 0)
+				goto out;
+			else
+				f_entries++;
+		}
+
+		entry = (char *)entry + len + 4;
+	}
+
+	printk(KERN_INFO "DWARF unwinder initialised: read %u CIEs, %u FDEs\n",
+	       c_entries, f_entries);
+
+	err = unwinder_register(&dwarf_unwinder);
+	if (err)
+		goto out;
+
+	return;
+
+out:
+	printk(KERN_ERR "Failed to initialise DWARF unwinder: %d\n", err);
+	dwarf_unwinder_cleanup();
+}
diff --git a/arch/sh/kernel/early_printk.c b/arch/sh/kernel/early_printk.c
index a952dcf9999d..81a46145ffa5 100644
--- a/arch/sh/kernel/early_printk.c
+++ b/arch/sh/kernel/early_printk.c
@@ -134,7 +134,7 @@ static void scif_sercon_init(char *s)
 	sci_out(&scif_port, SCFCR, 0x0030);	/* TTRG=b'11 */
 	sci_out(&scif_port, SCSCR, 0x0030);	/* TE, RE */
 }
-#elif defined(CONFIG_CPU_SH4)
+#elif defined(CONFIG_CPU_SH4) || defined(CONFIG_CPU_SH3)
 #define DEFAULT_BAUD 115200
 /*
  * Simple SCIF init, primarily aimed at SH7750 and other similar SH-4
@@ -220,8 +220,7 @@ static int __init setup_early_printk(char *buf)
 		early_console = &scif_console;
 
 #if !defined(CONFIG_SH_STANDARD_BIOS)
-#if defined(CONFIG_CPU_SH4) || defined(CONFIG_CPU_SUBTYPE_SH7720) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7721)
+#if defined(CONFIG_CPU_SH4) || defined(CONFIG_CPU_SH3)
 		scif_sercon_init(buf + 6);
 #endif
 #endif
diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S
index d62359cfbbe2..e63178fefb9b 100644
--- a/arch/sh/kernel/entry-common.S
+++ b/arch/sh/kernel/entry-common.S
@@ -43,9 +43,10 @@
  *	syscall #
  *
  */
+#include <asm/dwarf.h>
 
 #if defined(CONFIG_PREEMPT)
-#  define preempt_stop()	cli
+#  define preempt_stop()	cli ; TRACE_IRQS_OFF
 #else
 #  define preempt_stop()
 #  define resume_kernel		__restore_all
@@ -55,11 +56,7 @@
 	.align	2
 ENTRY(exception_error)
 	!
-#ifdef CONFIG_TRACE_IRQFLAGS
-	mov.l	2f, r0
-	jsr	@r0
-	 nop
-#endif
+	TRACE_IRQS_ON
 	sti
 	mov.l	1f, r0
 	jmp	@r0
@@ -67,22 +64,28 @@ ENTRY(exception_error)
 
 	.align	2
 1:	.long	do_exception_error
-#ifdef CONFIG_TRACE_IRQFLAGS
-2:	.long	trace_hardirqs_on
-#endif
 
 	.align	2
 ret_from_exception:
+	CFI_STARTPROC simple
+	CFI_DEF_CFA r14, 0
+	CFI_REL_OFFSET 17, 64
+	CFI_REL_OFFSET 15, 0
+	CFI_REL_OFFSET 14, 56
 	preempt_stop()
-#ifdef CONFIG_TRACE_IRQFLAGS
-	mov.l	4f, r0
-	jsr	@r0
-	 nop
-#endif
 ENTRY(ret_from_irq)
 	!
 	mov	#OFF_SR, r0
 	mov.l	@(r0,r15), r0	! get status register
+
+	shlr2	r0
+	and	#0x3c, r0
+	cmp/eq	#0x3c, r0
+	bt	9f
+	TRACE_IRQS_ON
+9:
+	mov	#OFF_SR, r0
+	mov.l	@(r0,r15), r0	! get status register
 	shll	r0
 	shll	r0		! kernel space?
 	get_current_thread_info r8, r0
@@ -125,13 +128,9 @@ noresched:
 ENTRY(resume_userspace)
 	! r8: current_thread_info
 	cli
-#ifdef CONFIG_TRACE_IRQFLAGS
-	mov.l	5f, r0
-	jsr	@r0
-	 nop
-#endif
+	TRACE_IRQS_OfF
 	mov.l	@(TI_FLAGS,r8), r0		! current_thread_info->flags
-	tst	#_TIF_WORK_MASK, r0
+	tst	#(_TIF_WORK_MASK & 0xff), r0
 	bt/s	__restore_all
 	 tst	#_TIF_NEED_RESCHED, r0
 
@@ -156,14 +155,10 @@ work_resched:
 	jsr	@r1				! schedule
 	 nop
 	cli
-#ifdef CONFIG_TRACE_IRQFLAGS
-	mov.l	5f, r0
-	jsr	@r0
-	 nop
-#endif
+	TRACE_IRQS_OFF
 	!
 	mov.l	@(TI_FLAGS,r8), r0		! current_thread_info->flags
-	tst	#_TIF_WORK_MASK, r0
+	tst	#(_TIF_WORK_MASK & 0xff), r0
 	bt	__restore_all
 	bra	work_pending
 	 tst	#_TIF_NEED_RESCHED, r0
@@ -172,23 +167,15 @@ work_resched:
 1:	.long	schedule
 2:	.long	do_notify_resume
 3:	.long	resume_userspace
-#ifdef CONFIG_TRACE_IRQFLAGS
-4:	.long	trace_hardirqs_on
-5:	.long	trace_hardirqs_off
-#endif
 
 	.align	2
 syscall_exit_work:
 	! r0: current_thread_info->flags
 	! r8: current_thread_info
-	tst	#_TIF_WORK_SYSCALL_MASK, r0
+	tst	#(_TIF_WORK_SYSCALL_MASK & 0xff), r0
 	bt/s	work_pending
 	 tst	#_TIF_NEED_RESCHED, r0
-#ifdef CONFIG_TRACE_IRQFLAGS
-	mov.l	5f, r0
-	jsr	@r0
-	 nop
-#endif
+	TRACE_IRQS_ON
 	sti
 	mov	r15, r4
 	mov.l	8f, r0			! do_syscall_trace_leave
@@ -259,6 +246,7 @@ debug_trap:
 	 nop
 	bra	__restore_all
 	 nop
+	CFI_ENDPROC
 
 	.align	2
 1:	.long	debug_trap_table
@@ -304,6 +292,7 @@ ret_from_fork:
  * system calls and debug traps through their respective jump tables.
  */
 ENTRY(system_call)
+	setup_frame_reg
 #if !defined(CONFIG_CPU_SH2)
 	mov.l	1f, r9
 	mov.l	@r9, r8		! Read from TRA (Trap Address) Register
@@ -321,18 +310,18 @@ ENTRY(system_call)
 	bt/s	debug_trap		! it's a debug trap..
 	 nop
 
-#ifdef CONFIG_TRACE_IRQFLAGS
-	mov.l	5f, r10
-	jsr	@r10
-	 nop
-#endif
+	TRACE_IRQS_ON
 	sti
 
 	!
 	get_current_thread_info r8, r10
 	mov.l	@(TI_FLAGS,r8), r8
-	mov	#_TIF_WORK_SYSCALL_MASK, r10
+	mov	#(_TIF_WORK_SYSCALL_MASK & 0xff), r10
+	mov	#(_TIF_WORK_SYSCALL_MASK >> 8), r9
 	tst	r10, r8
+	shll8	r9
+	bf	syscall_trace_entry
+	tst	r9, r8
 	bf	syscall_trace_entry
 	!
 	mov.l	2f, r8			! Number of syscalls
@@ -351,15 +340,15 @@ syscall_call:
 	!
 syscall_exit:
 	cli
-#ifdef CONFIG_TRACE_IRQFLAGS
-	mov.l	6f, r0
-	jsr	@r0
-	 nop
-#endif
+	TRACE_IRQS_OFF
 	!
 	get_current_thread_info r8, r0
 	mov.l	@(TI_FLAGS,r8), r0		! current_thread_info->flags
-	tst	#_TIF_ALLWORK_MASK, r0
+	tst	#(_TIF_ALLWORK_MASK & 0xff), r0
+	mov	#(_TIF_ALLWORK_MASK >> 8), r1
+	bf	syscall_exit_work
+	shlr8	r0
+	tst	r0, r1
 	bf	syscall_exit_work
 	bra	__restore_all
 	 nop
@@ -369,9 +358,5 @@ syscall_exit:
 #endif
 2:	.long	NR_syscalls
 3:	.long	sys_call_table
-#ifdef CONFIG_TRACE_IRQFLAGS
-5:	.long	trace_hardirqs_on
-6:	.long	trace_hardirqs_off
-#endif
 7:	.long	do_syscall_trace_enter
 8:	.long	do_syscall_trace_leave
diff --git a/arch/sh/kernel/ftrace.c b/arch/sh/kernel/ftrace.c
index 066f37dc32a9..6647dfcb781d 100644
--- a/arch/sh/kernel/ftrace.c
+++ b/arch/sh/kernel/ftrace.c
@@ -16,9 +16,13 @@
 #include <linux/string.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/kernel.h>
 #include <asm/ftrace.h>
 #include <asm/cacheflush.h>
+#include <asm/unistd.h>
+#include <trace/syscall.h>
 
+#ifdef CONFIG_DYNAMIC_FTRACE
 static unsigned char ftrace_replaced_code[MCOUNT_INSN_SIZE];
 
 static unsigned char ftrace_nop[4];
@@ -131,3 +135,189 @@ int __init ftrace_dyn_arch_init(void *data)
 
 	return 0;
 }
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+#ifdef CONFIG_DYNAMIC_FTRACE
+extern void ftrace_graph_call(void);
+
+static int ftrace_mod(unsigned long ip, unsigned long old_addr,
+		      unsigned long new_addr)
+{
+	unsigned char code[MCOUNT_INSN_SIZE];
+
+	if (probe_kernel_read(code, (void *)ip, MCOUNT_INSN_SIZE))
+		return -EFAULT;
+
+	if (old_addr != __raw_readl((unsigned long *)code))
+		return -EINVAL;
+
+	__raw_writel(new_addr, ip);
+	return 0;
+}
+
+int ftrace_enable_ftrace_graph_caller(void)
+{
+	unsigned long ip, old_addr, new_addr;
+
+	ip = (unsigned long)(&ftrace_graph_call) + GRAPH_INSN_OFFSET;
+	old_addr = (unsigned long)(&skip_trace);
+	new_addr = (unsigned long)(&ftrace_graph_caller);
+
+	return ftrace_mod(ip, old_addr, new_addr);
+}
+
+int ftrace_disable_ftrace_graph_caller(void)
+{
+	unsigned long ip, old_addr, new_addr;
+
+	ip = (unsigned long)(&ftrace_graph_call) + GRAPH_INSN_OFFSET;
+	old_addr = (unsigned long)(&ftrace_graph_caller);
+	new_addr = (unsigned long)(&skip_trace);
+
+	return ftrace_mod(ip, old_addr, new_addr);
+}
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
+/*
+ * Hook the return address and push it in the stack of return addrs
+ * in the current thread info.
+ *
+ * This is the main routine for the function graph tracer. The function
+ * graph tracer essentially works like this:
+ *
+ * parent is the stack address containing self_addr's return address.
+ * We pull the real return address out of parent and store it in
+ * current's ret_stack. Then, we replace the return address on the stack
+ * with the address of return_to_handler. self_addr is the function that
+ * called mcount.
+ *
+ * When self_addr returns, it will jump to return_to_handler which calls
+ * ftrace_return_to_handler. ftrace_return_to_handler will pull the real
+ * return address off of current's ret_stack and jump to it.
+ */
+void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
+{
+	unsigned long old;
+	int faulted, err;
+	struct ftrace_graph_ent trace;
+	unsigned long return_hooker = (unsigned long)&return_to_handler;
+
+	if (unlikely(atomic_read(&current->tracing_graph_pause)))
+		return;
+
+	/*
+	 * Protect against fault, even if it shouldn't
+	 * happen. This tool is too much intrusive to
+	 * ignore such a protection.
+	 */
+	__asm__ __volatile__(
+		"1:						\n\t"
+		"mov.l		@%2, %0				\n\t"
+		"2:						\n\t"
+		"mov.l		%3, @%2				\n\t"
+		"mov		#0, %1				\n\t"
+		"3:						\n\t"
+		".section .fixup, \"ax\"			\n\t"
+		"4:						\n\t"
+		"mov.l		5f, %0				\n\t"
+		"jmp		@%0				\n\t"
+		" mov		#1, %1				\n\t"
+		".balign 4					\n\t"
+		"5:	.long 3b				\n\t"
+		".previous					\n\t"
+		".section __ex_table,\"a\"			\n\t"
+		".long 1b, 4b					\n\t"
+		".long 2b, 4b					\n\t"
+		".previous					\n\t"
+		: "=&r" (old), "=r" (faulted)
+		: "r" (parent), "r" (return_hooker)
+	);
+
+	if (unlikely(faulted)) {
+		ftrace_graph_stop();
+		WARN_ON(1);
+		return;
+	}
+
+	err = ftrace_push_return_trace(old, self_addr, &trace.depth, 0);
+	if (err == -EBUSY) {
+		__raw_writel(old, parent);
+		return;
+	}
+
+	trace.func = self_addr;
+
+	/* Only trace if the calling function expects to */
+	if (!ftrace_graph_entry(&trace)) {
+		current->curr_ret_stack--;
+		__raw_writel(old, parent);
+	}
+}
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+
+#ifdef CONFIG_FTRACE_SYSCALLS
+
+extern unsigned long __start_syscalls_metadata[];
+extern unsigned long __stop_syscalls_metadata[];
+extern unsigned long *sys_call_table;
+
+static struct syscall_metadata **syscalls_metadata;
+
+static struct syscall_metadata *find_syscall_meta(unsigned long *syscall)
+{
+	struct syscall_metadata *start;
+	struct syscall_metadata *stop;
+	char str[KSYM_SYMBOL_LEN];
+
+
+	start = (struct syscall_metadata *)__start_syscalls_metadata;
+	stop = (struct syscall_metadata *)__stop_syscalls_metadata;
+	kallsyms_lookup((unsigned long) syscall, NULL, NULL, NULL, str);
+
+	for ( ; start < stop; start++) {
+		if (start->name && !strcmp(start->name, str))
+			return start;
+	}
+
+	return NULL;
+}
+
+#define FTRACE_SYSCALL_MAX	(NR_syscalls - 1)
+
+struct syscall_metadata *syscall_nr_to_meta(int nr)
+{
+	if (!syscalls_metadata || nr >= FTRACE_SYSCALL_MAX || nr < 0)
+		return NULL;
+
+	return syscalls_metadata[nr];
+}
+
+void arch_init_ftrace_syscalls(void)
+{
+	int i;
+	struct syscall_metadata *meta;
+	unsigned long **psys_syscall_table = &sys_call_table;
+	static atomic_t refs;
+
+	if (atomic_inc_return(&refs) != 1)
+		goto end;
+
+	syscalls_metadata = kzalloc(sizeof(*syscalls_metadata) *
+					FTRACE_SYSCALL_MAX, GFP_KERNEL);
+	if (!syscalls_metadata) {
+		WARN_ON(1);
+		return;
+	}
+
+	for (i = 0; i < FTRACE_SYSCALL_MAX; i++) {
+		meta = find_syscall_meta(psys_syscall_table[i]);
+		syscalls_metadata[i] = meta;
+	}
+	return;
+
+	/* Paranoid: avoid overflow */
+end:
+	atomic_dec(&refs);
+}
+#endif /* CONFIG_FTRACE_SYSCALLS */
diff --git a/arch/sh/kernel/io_trapped.c b/arch/sh/kernel/io_trapped.c
index 77dfecb64373..e27a19e1f46e 100644
--- a/arch/sh/kernel/io_trapped.c
+++ b/arch/sh/kernel/io_trapped.c
@@ -112,14 +112,15 @@ void __iomem *match_trapped_io_handler(struct list_head *list,
 	struct trapped_io *tiop;
 	struct resource *res;
 	int k, len;
+	unsigned long flags;
 
-	spin_lock_irq(&trapped_lock);
+	spin_lock_irqsave(&trapped_lock, flags);
 	list_for_each_entry(tiop, list, list) {
 		voffs = 0;
 		for (k = 0; k < tiop->num_resources; k++) {
 			res = tiop->resource + k;
 			if (res->start == offset) {
-				spin_unlock_irq(&trapped_lock);
+				spin_unlock_irqrestore(&trapped_lock, flags);
 				return tiop->virt_base + voffs;
 			}
 
@@ -127,7 +128,7 @@ void __iomem *match_trapped_io_handler(struct list_head *list,
 			voffs += roundup(len, PAGE_SIZE);
 		}
 	}
-	spin_unlock_irq(&trapped_lock);
+	spin_unlock_irqrestore(&trapped_lock, flags);
 	return NULL;
 }
 EXPORT_SYMBOL_GPL(match_trapped_io_handler);
diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c
index 3d09062f4682..2bb43dc74f22 100644
--- a/arch/sh/kernel/irq.c
+++ b/arch/sh/kernel/irq.c
@@ -14,6 +14,7 @@
 #include <asm/processor.h>
 #include <asm/machvec.h>
 #include <asm/uaccess.h>
+#include <asm/dwarf.h>
 #include <asm/thread_info.h>
 #include <cpu/mmu_context.h>
 
@@ -114,23 +115,6 @@ asmlinkage int do_IRQ(unsigned int irq, struct pt_regs *regs)
 #endif
 
 	irq_enter();
-
-#ifdef CONFIG_DEBUG_STACKOVERFLOW
-	/* Debugging check for stack overflow: is there less than 1KB free? */
-	{
-		long sp;
-
-		__asm__ __volatile__ ("and r15, %0" :
-					"=r" (sp) : "0" (THREAD_SIZE - 1));
-
-		if (unlikely(sp < (sizeof(struct thread_info) + STACK_WARN))) {
-			printk("do_IRQ: stack overflow: %ld\n",
-			       sp - sizeof(struct thread_info));
-			dump_stack();
-		}
-	}
-#endif
-
 	irq = irq_demux(intc_evt2irq(irq));
 
 #ifdef CONFIG_IRQSTACKS
@@ -278,6 +262,9 @@ void __init init_IRQ(void)
 		sh_mv.mv_init_irq();
 
 	irq_ctx_init(smp_processor_id());
+
+	/* This needs to be early, but not too early.. */
+	dwarf_unwinder_init();
 }
 
 #ifdef CONFIG_SPARSE_IRQ
diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c
index 92d7740faab1..9fee977f176b 100644
--- a/arch/sh/kernel/process_32.c
+++ b/arch/sh/kernel/process_32.c
@@ -23,6 +23,7 @@
 #include <linux/tick.h>
 #include <linux/reboot.h>
 #include <linux/fs.h>
+#include <linux/ftrace.h>
 #include <linux/preempt.h>
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
@@ -264,8 +265,8 @@ static void ubc_set_tracing(int asid, unsigned long pc)
  *	switch_to(x,y) should switch tasks from x to y.
  *
  */
-struct task_struct *__switch_to(struct task_struct *prev,
-				struct task_struct *next)
+__notrace_funcgraph struct task_struct *
+__switch_to(struct task_struct *prev, struct task_struct *next)
 {
 #if defined(CONFIG_SH_FPU)
 	unlazy_fpu(prev, task_pt_regs(prev));
diff --git a/arch/sh/kernel/ptrace_32.c b/arch/sh/kernel/ptrace_32.c
index 3392e835a374..c198eceaee94 100644
--- a/arch/sh/kernel/ptrace_32.c
+++ b/arch/sh/kernel/ptrace_32.c
@@ -34,6 +34,8 @@
 #include <asm/syscalls.h>
 #include <asm/fpu.h>
 
+#include <trace/syscall.h>
+
 /*
  * This routine will get a word off of the process kernel stack.
  */
@@ -459,6 +461,9 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
 		 */
 		ret = -1L;
 
+	if (unlikely(test_thread_flag(TIF_SYSCALL_FTRACE)))
+		ftrace_syscall_enter(regs);
+
 	if (unlikely(current->audit_context))
 		audit_syscall_entry(audit_arch(), regs->regs[3],
 				    regs->regs[4], regs->regs[5],
@@ -475,6 +480,9 @@ asmlinkage void do_syscall_trace_leave(struct pt_regs *regs)
 		audit_syscall_exit(AUDITSC_RESULT(regs->regs[0]),
 				   regs->regs[0]);
 
+	if (unlikely(test_thread_flag(TIF_SYSCALL_FTRACE)))
+		ftrace_syscall_exit(regs);
+
 	step = test_thread_flag(TIF_SINGLESTEP);
 	if (step || test_thread_flag(TIF_SYSCALL_TRACE))
 		tracehook_report_syscall_exit(regs, step);
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index dd38338553ef..ceb409bf7741 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -30,6 +30,7 @@
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/platform_device.h>
+#include <linux/lmb.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/page.h>
@@ -233,39 +234,45 @@ void __init __add_active_range(unsigned int nid, unsigned long start_pfn,
 void __init setup_bootmem_allocator(unsigned long free_pfn)
 {
 	unsigned long bootmap_size;
+	unsigned long bootmap_pages, bootmem_paddr;
+	u64 total_pages = (lmb_end_of_DRAM() - __MEMORY_START) >> PAGE_SHIFT;
+	int i;
+
+	bootmap_pages = bootmem_bootmap_pages(total_pages);
+
+	bootmem_paddr = lmb_alloc(bootmap_pages << PAGE_SHIFT, PAGE_SIZE);
 
 	/*
 	 * Find a proper area for the bootmem bitmap. After this
 	 * bootstrap step all allocations (until the page allocator
 	 * is intact) must be done via bootmem_alloc().
 	 */
-	bootmap_size = init_bootmem_node(NODE_DATA(0), free_pfn,
+	bootmap_size = init_bootmem_node(NODE_DATA(0),
+					 bootmem_paddr >> PAGE_SHIFT,
 					 min_low_pfn, max_low_pfn);
 
-	__add_active_range(0, min_low_pfn, max_low_pfn);
+	/* Add active regions with valid PFNs. */
+	for (i = 0; i < lmb.memory.cnt; i++) {
+		unsigned long start_pfn, end_pfn;
+		start_pfn = lmb.memory.region[i].base >> PAGE_SHIFT;
+		end_pfn = start_pfn + lmb_size_pages(&lmb.memory, i);
+		__add_active_range(0, start_pfn, end_pfn);
+	}
+
+	/*
+	 * Add all physical memory to the bootmem map and mark each
+	 * area as present.
+	 */
 	register_bootmem_low_pages();
 
-	node_set_online(0);
-
-	/*
-	 * Reserve the kernel text and
-	 * Reserve the bootmem bitmap. We do this in two steps (first step
-	 * was init_bootmem()), because this catches the (definitely buggy)
-	 * case of us accidentally initializing the bootmem allocator with
-	 * an invalid RAM area.
-	 */
-	reserve_bootmem(__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET,
-			(PFN_PHYS(free_pfn) + bootmap_size + PAGE_SIZE - 1) -
-			(__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET),
-			BOOTMEM_DEFAULT);
-
-	/*
-	 * Reserve physical pages below CONFIG_ZERO_PAGE_OFFSET.
-	 */
-	if (CONFIG_ZERO_PAGE_OFFSET != 0)
-		reserve_bootmem(__MEMORY_START, CONFIG_ZERO_PAGE_OFFSET,
+	/* Reserve the sections we're already using. */
+	for (i = 0; i < lmb.reserved.cnt; i++)
+		reserve_bootmem(lmb.reserved.region[i].base,
+				lmb_size_bytes(&lmb.reserved, i),
 				BOOTMEM_DEFAULT);
 
+	node_set_online(0);
+
 	sparse_memory_present_with_active_regions(0);
 
 #ifdef CONFIG_BLK_DEV_INITRD
@@ -296,12 +303,37 @@ void __init setup_bootmem_allocator(unsigned long free_pfn)
 static void __init setup_memory(void)
 {
 	unsigned long start_pfn;
+	u64 base = min_low_pfn << PAGE_SHIFT;
+	u64 size = (max_low_pfn << PAGE_SHIFT) - base;
 
 	/*
 	 * Partially used pages are not usable - thus
 	 * we are rounding upwards:
 	 */
 	start_pfn = PFN_UP(__pa(_end));
+
+	lmb_add(base, size);
+
+	/*
+	 * Reserve the kernel text and
+	 * Reserve the bootmem bitmap. We do this in two steps (first step
+	 * was init_bootmem()), because this catches the (definitely buggy)
+	 * case of us accidentally initializing the bootmem allocator with
+	 * an invalid RAM area.
+	 */
+	lmb_reserve(__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET,
+		    (PFN_PHYS(start_pfn) + PAGE_SIZE - 1) -
+		    (__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET));
+
+	/*
+	 * Reserve physical pages below CONFIG_ZERO_PAGE_OFFSET.
+	 */
+	if (CONFIG_ZERO_PAGE_OFFSET != 0)
+		lmb_reserve(__MEMORY_START, CONFIG_ZERO_PAGE_OFFSET);
+
+	lmb_analyze();
+	lmb_dump_all();
+
 	setup_bootmem_allocator(start_pfn);
 }
 #else
@@ -402,6 +434,7 @@ void __init setup_arch(char **cmdline_p)
 	nodes_clear(node_online_map);
 
 	/* Setup bootmem with available RAM */
+	lmb_init();
 	setup_memory();
 	sparse_init();
 
diff --git a/arch/sh/kernel/sh_ksyms_32.c b/arch/sh/kernel/sh_ksyms_32.c
index fcc5de31f83b..cec610888e28 100644
--- a/arch/sh/kernel/sh_ksyms_32.c
+++ b/arch/sh/kernel/sh_ksyms_32.c
@@ -106,8 +106,8 @@ EXPORT_SYMBOL(flush_dcache_page);
 EXPORT_SYMBOL(clear_user_page);
 #endif
 
-#ifdef CONFIG_FUNCTION_TRACER
-EXPORT_SYMBOL(mcount);
+#ifdef CONFIG_MCOUNT
+DECLARE_EXPORT(mcount);
 #endif
 EXPORT_SYMBOL(csum_partial);
 EXPORT_SYMBOL(csum_partial_copy_generic);
diff --git a/arch/sh/kernel/stacktrace.c b/arch/sh/kernel/stacktrace.c
index 1a2a5eb76e41..c2e45c48409c 100644
--- a/arch/sh/kernel/stacktrace.c
+++ b/arch/sh/kernel/stacktrace.c
@@ -13,47 +13,93 @@
 #include <linux/stacktrace.h>
 #include <linux/thread_info.h>
 #include <linux/module.h>
+#include <asm/unwinder.h>
 #include <asm/ptrace.h>
+#include <asm/stacktrace.h>
+
+static void save_stack_warning(void *data, char *msg)
+{
+}
+
+static void
+save_stack_warning_symbol(void *data, char *msg, unsigned long symbol)
+{
+}
+
+static int save_stack_stack(void *data, char *name)
+{
+	return 0;
+}
 
 /*
  * Save stack-backtrace addresses into a stack_trace buffer.
  */
+static void save_stack_address(void *data, unsigned long addr, int reliable)
+{
+	struct stack_trace *trace = data;
+
+	if (!reliable)
+		return;
+
+	if (trace->skip > 0) {
+		trace->skip--;
+		return;
+	}
+
+	if (trace->nr_entries < trace->max_entries)
+		trace->entries[trace->nr_entries++] = addr;
+}
+
+static const struct stacktrace_ops save_stack_ops = {
+	.warning = save_stack_warning,
+	.warning_symbol = save_stack_warning_symbol,
+	.stack = save_stack_stack,
+	.address = save_stack_address,
+};
+
 void save_stack_trace(struct stack_trace *trace)
 {
 	unsigned long *sp = (unsigned long *)current_stack_pointer;
 
-	while (!kstack_end(sp)) {
-		unsigned long addr = *sp++;
-
-		if (__kernel_text_address(addr)) {
-			if (trace->skip > 0)
-				trace->skip--;
-			else
-				trace->entries[trace->nr_entries++] = addr;
-			if (trace->nr_entries >= trace->max_entries)
-				break;
-		}
-	}
+	unwind_stack(current, NULL, sp,  &save_stack_ops, trace);
+	if (trace->nr_entries < trace->max_entries)
+		trace->entries[trace->nr_entries++] = ULONG_MAX;
 }
 EXPORT_SYMBOL_GPL(save_stack_trace);
 
+static void
+save_stack_address_nosched(void *data, unsigned long addr, int reliable)
+{
+	struct stack_trace *trace = (struct stack_trace *)data;
+
+	if (!reliable)
+		return;
+
+	if (in_sched_functions(addr))
+		return;
+
+	if (trace->skip > 0) {
+		trace->skip--;
+		return;
+	}
+
+	if (trace->nr_entries < trace->max_entries)
+		trace->entries[trace->nr_entries++] = addr;
+}
+
+static const struct stacktrace_ops save_stack_ops_nosched = {
+	.warning = save_stack_warning,
+	.warning_symbol = save_stack_warning_symbol,
+	.stack = save_stack_stack,
+	.address = save_stack_address_nosched,
+};
+
 void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
 {
 	unsigned long *sp = (unsigned long *)tsk->thread.sp;
 
-	while (!kstack_end(sp)) {
-		unsigned long addr = *sp++;
-
-		if (__kernel_text_address(addr)) {
-			if (in_sched_functions(addr))
-				break;
-			if (trace->skip > 0)
-				trace->skip--;
-			else
-				trace->entries[trace->nr_entries++] = addr;
-			if (trace->nr_entries >= trace->max_entries)
-				break;
-		}
-	}
+	unwind_stack(current, NULL, sp,  &save_stack_ops_nosched, trace);
+	if (trace->nr_entries < trace->max_entries)
+		trace->entries[trace->nr_entries++] = ULONG_MAX;
 }
 EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c
index 9b352a1e3fb4..7f95f479060f 100644
--- a/arch/sh/kernel/time.c
+++ b/arch/sh/kernel/time.c
@@ -21,6 +21,7 @@
 #include <linux/smp.h>
 #include <linux/rtc.h>
 #include <asm/clock.h>
+#include <asm/hwblk.h>
 #include <asm/rtc.h>
 
 /* Dummy RTC ops */
@@ -91,21 +92,8 @@ module_init(rtc_generic_init);
 
 void (*board_time_init)(void);
 
-void __init time_init(void)
+static void __init sh_late_time_init(void)
 {
-	if (board_time_init)
-		board_time_init();
-
-	clk_init();
-
-	rtc_sh_get_time(&xtime);
-	set_normalized_timespec(&wall_to_monotonic,
-				-xtime.tv_sec, -xtime.tv_nsec);
-
-#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
-	local_timer_setup(smp_processor_id());
-#endif
-
 	/*
 	 * Make sure all compiled-in early timers register themselves.
 	 *
@@ -118,3 +106,22 @@ void __init time_init(void)
 	early_platform_driver_register_all("earlytimer");
 	early_platform_driver_probe("earlytimer", 2, 0);
 }
+
+void __init time_init(void)
+{
+	if (board_time_init)
+		board_time_init();
+
+	hwblk_init();
+	clk_init();
+
+	rtc_sh_get_time(&xtime);
+	set_normalized_timespec(&wall_to_monotonic,
+				-xtime.tv_sec, -xtime.tv_nsec);
+
+#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
+	local_timer_setup(smp_processor_id());
+#endif
+
+	late_time_init = sh_late_time_init;
+}
diff --git a/arch/sh/kernel/traps_32.c b/arch/sh/kernel/traps_32.c
index 2b772776fcda..563426487c6b 100644
--- a/arch/sh/kernel/traps_32.c
+++ b/arch/sh/kernel/traps_32.c
@@ -858,30 +858,6 @@ void __init trap_init(void)
 	per_cpu_trap_init();
 }
 
-void show_trace(struct task_struct *tsk, unsigned long *sp,
-		struct pt_regs *regs)
-{
-	unsigned long addr;
-
-	if (regs && user_mode(regs))
-		return;
-
-	printk("\nCall trace:\n");
-
-	while (!kstack_end(sp)) {
-		addr = *sp++;
-		if (kernel_text_address(addr))
-			print_ip_sym(addr);
-	}
-
-	printk("\n");
-
-	if (!tsk)
-		tsk = current;
-
-	debug_show_held_locks(tsk);
-}
-
 void show_stack(struct task_struct *tsk, unsigned long *sp)
 {
 	unsigned long stack;
diff --git a/arch/sh/kernel/unwinder.c b/arch/sh/kernel/unwinder.c
new file mode 100644
index 000000000000..2b30fa28b440
--- /dev/null
+++ b/arch/sh/kernel/unwinder.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2009  Matt Fleming
+ *
+ * Based, in part, on kernel/time/clocksource.c.
+ *
+ * This file provides arbitration code for stack unwinders.
+ *
+ * Multiple stack unwinders can be available on a system, usually with
+ * the most accurate unwinder being the currently active one.
+ */
+#include <linux/errno.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <asm/unwinder.h>
+#include <asm/atomic.h>
+
+/*
+ * This is the most basic stack unwinder an architecture can
+ * provide. For architectures without reliable frame pointers, e.g.
+ * RISC CPUs, it can be implemented by looking through the stack for
+ * addresses that lie within the kernel text section.
+ *
+ * Other CPUs, e.g. x86, can use their frame pointer register to
+ * construct more accurate stack traces.
+ */
+static struct list_head unwinder_list;
+static struct unwinder stack_reader = {
+	.name = "stack-reader",
+	.dump = stack_reader_dump,
+	.rating = 50,
+	.list = {
+		.next = &unwinder_list,
+		.prev = &unwinder_list,
+	},
+};
+
+/*
+ * "curr_unwinder" points to the stack unwinder currently in use. This
+ * is the unwinder with the highest rating.
+ *
+ * "unwinder_list" is a linked-list of all available unwinders, sorted
+ * by rating.
+ *
+ * All modifications of "curr_unwinder" and "unwinder_list" must be
+ * performed whilst holding "unwinder_lock".
+ */
+static struct unwinder *curr_unwinder = &stack_reader;
+
+static struct list_head unwinder_list = {
+	.next = &stack_reader.list,
+	.prev = &stack_reader.list,
+};
+
+static DEFINE_SPINLOCK(unwinder_lock);
+
+static atomic_t unwinder_running = ATOMIC_INIT(0);
+
+/**
+ * select_unwinder - Select the best registered stack unwinder.
+ *
+ * Private function. Must hold unwinder_lock when called.
+ *
+ * Select the stack unwinder with the best rating. This is useful for
+ * setting up curr_unwinder.
+ */
+static struct unwinder *select_unwinder(void)
+{
+	struct unwinder *best;
+
+	if (list_empty(&unwinder_list))
+		return NULL;
+
+	best = list_entry(unwinder_list.next, struct unwinder, list);
+	if (best == curr_unwinder)
+		return NULL;
+
+	return best;
+}
+
+/*
+ * Enqueue the stack unwinder sorted by rating.
+ */
+static int unwinder_enqueue(struct unwinder *ops)
+{
+	struct list_head *tmp, *entry = &unwinder_list;
+
+	list_for_each(tmp, &unwinder_list) {
+		struct unwinder *o;
+
+		o = list_entry(tmp, struct unwinder, list);
+		if (o == ops)
+			return -EBUSY;
+		/* Keep track of the place, where to insert */
+		if (o->rating >= ops->rating)
+			entry = tmp;
+	}
+	list_add(&ops->list, entry);
+
+	return 0;
+}
+
+/**
+ * unwinder_register - Used to install new stack unwinder
+ * @u: unwinder to be registered
+ *
+ * Install the new stack unwinder on the unwinder list, which is sorted
+ * by rating.
+ *
+ * Returns -EBUSY if registration fails, zero otherwise.
+ */
+int unwinder_register(struct unwinder *u)
+{
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&unwinder_lock, flags);
+	ret = unwinder_enqueue(u);
+	if (!ret)
+		curr_unwinder = select_unwinder();
+	spin_unlock_irqrestore(&unwinder_lock, flags);
+
+	return ret;
+}
+
+/*
+ * Unwind the call stack and pass information to the stacktrace_ops
+ * functions. Also handle the case where we need to switch to a new
+ * stack dumper because the current one faulted unexpectedly.
+ */
+void unwind_stack(struct task_struct *task, struct pt_regs *regs,
+		  unsigned long *sp, const struct stacktrace_ops *ops,
+		  void *data)
+{
+	unsigned long flags;
+
+	/*
+	 * The problem with unwinders with high ratings is that they are
+	 * inherently more complicated than the simple ones with lower
+	 * ratings. We are therefore more likely to fault in the
+	 * complicated ones, e.g. hitting BUG()s. If we fault in the
+	 * code for the current stack unwinder we try to downgrade to
+	 * one with a lower rating.
+	 *
+	 * Hopefully this will give us a semi-reliable stacktrace so we
+	 * can diagnose why curr_unwinder->dump() faulted.
+	 */
+	if (atomic_inc_return(&unwinder_running) != 1) {
+		spin_lock_irqsave(&unwinder_lock, flags);
+
+		if (!list_is_singular(&unwinder_list)) {
+			list_del(&curr_unwinder->list);
+			curr_unwinder = select_unwinder();
+		}
+
+		spin_unlock_irqrestore(&unwinder_lock, flags);
+		atomic_dec(&unwinder_running);
+	}
+
+	curr_unwinder->dump(task, regs, sp, ops, data);
+
+	atomic_dec(&unwinder_running);
+}
diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S
index f53c76acaede..1b7d9d541e01 100644
--- a/arch/sh/kernel/vmlinux.lds.S
+++ b/arch/sh/kernel/vmlinux.lds.S
@@ -12,7 +12,7 @@ OUTPUT_ARCH(sh)
 
 #include <asm/thread_info.h>
 #include <asm/cache.h>
-#include <asm-generic/vmlinux.lds.h>
+#include <asm/vmlinux.lds.h>
 
 ENTRY(_start)
 SECTIONS
@@ -50,12 +50,7 @@ SECTIONS
 		_etext = .;		/* End of text section */
 	} = 0x0009
 
-	. = ALIGN(16);		/* Exception table */
-	__ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) {
-		__start___ex_table = .;
-		*(__ex_table)
-		__stop___ex_table = .;
-	}
+	EXCEPTION_TABLE(16)
 
 	NOTES
 	RO_DATA(PAGE_SIZE)
@@ -71,69 +66,16 @@ SECTIONS
 		__uncached_end = .;
 	}
 
-	. = ALIGN(THREAD_SIZE);
-	.data : AT(ADDR(.data) - LOAD_OFFSET) {		/* Data */
-		*(.data.init_task)
-
-		. = ALIGN(L1_CACHE_BYTES);
-		*(.data.cacheline_aligned)
-
-		. = ALIGN(L1_CACHE_BYTES);
-		*(.data.read_mostly)
-
-		. = ALIGN(PAGE_SIZE);
-		*(.data.page_aligned)
-
-		__nosave_begin = .;
-		*(.data.nosave)
-		. = ALIGN(PAGE_SIZE);
-		__nosave_end = .;
-
-		DATA_DATA
-		CONSTRUCTORS
-	}
+	RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
 
 	_edata = .;			/* End of data section */
 
+	DWARF_EH_FRAME
+
 	. = ALIGN(PAGE_SIZE);		/* Init code and data */
-	.init.text : AT(ADDR(.init.text) - LOAD_OFFSET) {
-		__init_begin = .;
-		_sinittext = .;
-		INIT_TEXT
-		_einittext = .;
-	}
-
-	.init.data : AT(ADDR(.init.data) - LOAD_OFFSET) { INIT_DATA }
-
-	. = ALIGN(16);
-	.init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) {
-		__setup_start = .;
-		*(.init.setup)
-		__setup_end = .;
-	}
-
-	.initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET) {
-		__initcall_start = .;
-		INITCALLS
-		__initcall_end = .;
-	}
-
-	.con_initcall.init : AT(ADDR(.con_initcall.init) - LOAD_OFFSET) {
-		__con_initcall_start = .;
-		*(.con_initcall.init)
-		__con_initcall_end = .;
-	}
-
-	SECURITY_INIT
-
-#ifdef CONFIG_BLK_DEV_INITRD
-	. = ALIGN(PAGE_SIZE);
-	.init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) {
-		__initramfs_start = .;
-		*(.init.ramfs)
-		__initramfs_end = .;
-	}
-#endif
+	__init_begin = .;
+	INIT_TEXT_SECTION(PAGE_SIZE)
+	INIT_DATA_SECTION(16)
 
 	. = ALIGN(4);
 	.machvec.init : AT(ADDR(.machvec.init) - LOAD_OFFSET) {
@@ -152,16 +94,10 @@ SECTIONS
 	.exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) { EXIT_DATA }
 
 	. = ALIGN(PAGE_SIZE);
-	.bss : AT(ADDR(.bss) - LOAD_OFFSET) {
-		__init_end = .;
-		__bss_start = .;		/* BSS */
-		*(.bss.page_aligned)
-		*(.bss)
-		*(COMMON)
-		. = ALIGN(4);
-		_ebss = .;			/* uClinux MTD sucks */
-		_end = . ;
-	}
+	__init_end = .;
+	BSS_SECTION(0, PAGE_SIZE, 4)
+	_ebss = .;			/* uClinux MTD sucks */
+	_end = . ;
 
 	/*
 	 * When something in the kernel is NOT compiled as a module, the
@@ -170,7 +106,7 @@ SECTIONS
 	 * it's a module.
 	 */
 	/DISCARD/ : {
-		*(.exitcall.exit)
+		EXIT_CALL
 	}
 
 	STABS_DEBUG
diff --git a/arch/sh/lib/Makefile b/arch/sh/lib/Makefile
index aaea580b65bb..c2b28d8b2dd1 100644
--- a/arch/sh/lib/Makefile
+++ b/arch/sh/lib/Makefile
@@ -24,7 +24,7 @@ memcpy-y			:= memcpy.o
 memcpy-$(CONFIG_CPU_SH4)	:= memcpy-sh4.o
 
 lib-$(CONFIG_MMU)		+= copy_page.o clear_page.o
-lib-$(CONFIG_FUNCTION_TRACER)	+= mcount.o
+lib-$(CONFIG_MCOUNT)		+= mcount.o
 lib-y				+= $(memcpy-y) $(udivsi3-y)
 
 EXTRA_CFLAGS += -Werror
diff --git a/arch/sh/lib/mcount.S b/arch/sh/lib/mcount.S
index 110fbfe1831f..84a57761f17e 100644
--- a/arch/sh/lib/mcount.S
+++ b/arch/sh/lib/mcount.S
@@ -1,14 +1,16 @@
 /*
  * arch/sh/lib/mcount.S
  *
- *  Copyright (C) 2008  Paul Mundt
- *  Copyright (C) 2008  Matt Fleming
+ *  Copyright (C) 2008, 2009  Paul Mundt
+ *  Copyright (C) 2008, 2009  Matt Fleming
  *
  * 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 <asm/ftrace.h>
+#include <asm/thread_info.h>
+#include <asm/asm-offsets.h>
 
 #define MCOUNT_ENTER()		\
 	mov.l	r4, @-r15;	\
@@ -28,6 +30,55 @@
 	rts;			\
 	 mov.l	@r15+, r4
 
+#ifdef CONFIG_STACK_DEBUG
+/*
+ * Perform diagnostic checks on the state of the kernel stack.
+ *
+ * Check for stack overflow. If there is less than 1KB free
+ * then it has overflowed.
+ *
+ * Make sure the stack pointer contains a valid address. Valid
+ * addresses for kernel stacks are anywhere after the bss
+ * (after _ebss) and anywhere in init_thread_union (init_stack).
+ */
+#define STACK_CHECK()					\
+	mov	#(THREAD_SIZE >> 10), r0;		\
+	shll8	r0;					\
+	shll2	r0;					\
+							\
+	/* r1 = sp & (THREAD_SIZE - 1) */		\
+	mov	#-1, r1;				\
+	add	r0, r1;					\
+	and	r15, r1;				\
+							\
+	mov	#TI_SIZE, r3;				\
+	mov	#(STACK_WARN >> 8), r2;			\
+	shll8	r2;					\
+	add	r3, r2;					\
+							\
+	/* Is the stack overflowing? */			\
+	cmp/hi	r2, r1;					\
+	bf	stack_panic;				\
+							\
+	/* If sp > _ebss then we're OK. */		\
+	mov.l	.L_ebss, r1;				\
+	cmp/hi	r1, r15;				\
+	bt	1f;					\
+							\
+	/* If sp < init_stack, we're not OK. */		\
+	mov.l	.L_init_thread_union, r1;		\
+	cmp/hs	r1, r15;				\
+	bf	stack_panic;				\
+							\
+	/* If sp > init_stack && sp < _ebss, not OK. */	\
+	add	r0, r1;					\
+	cmp/hs	r1, r15;				\
+	bt	stack_panic;				\
+1:
+#else
+#define STACK_CHECK()
+#endif /* CONFIG_STACK_DEBUG */
+
 	.align 2
 	.globl	_mcount
 	.type	_mcount,@function
@@ -35,6 +86,19 @@
 	.type	mcount,@function
 _mcount:
 mcount:
+	STACK_CHECK()
+
+#ifndef CONFIG_FUNCTION_TRACER
+	rts
+	 nop
+#else
+#ifndef CONFIG_DYNAMIC_FTRACE
+	mov.l	.Lfunction_trace_stop, r0
+	mov.l	@r0, r0
+	tst	r0, r0
+	bf	ftrace_stub
+#endif
+
 	MCOUNT_ENTER()
 
 #ifdef CONFIG_DYNAMIC_FTRACE
@@ -52,16 +116,69 @@ mcount_call:
 	jsr	@r6
 	 nop
 
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	mov.l   .Lftrace_graph_return, r6
+	mov.l   .Lftrace_stub, r7
+	cmp/eq  r6, r7
+	bt      1f
+
+	mov.l   .Lftrace_graph_caller, r0
+	jmp     @r0
+	 nop
+
+1:
+	mov.l	.Lftrace_graph_entry, r6
+	mov.l	.Lftrace_graph_entry_stub, r7
+	cmp/eq	r6, r7
+	bt	skip_trace
+
+	mov.l   .Lftrace_graph_caller, r0
+	jmp	@r0
+	 nop
+
+	.align 2
+.Lftrace_graph_return:
+	.long   ftrace_graph_return
+.Lftrace_graph_entry:
+	.long   ftrace_graph_entry
+.Lftrace_graph_entry_stub:
+	.long   ftrace_graph_entry_stub
+.Lftrace_graph_caller:
+	.long   ftrace_graph_caller
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+
+	.globl skip_trace
 skip_trace:
 	MCOUNT_LEAVE()
 
 	.align 2
 .Lftrace_trace_function:
-	.long	ftrace_trace_function
+	.long   ftrace_trace_function
 
 #ifdef CONFIG_DYNAMIC_FTRACE
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+/*
+ * NOTE: Do not move either ftrace_graph_call or ftrace_caller
+ * as this will affect the calculation of GRAPH_INSN_OFFSET.
+ */
+	.globl ftrace_graph_call
+ftrace_graph_call:
+	mov.l	.Lskip_trace, r0
+	jmp	@r0
+	 nop
+
+	.align 2
+.Lskip_trace:
+	.long	skip_trace
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+
 	.globl ftrace_caller
 ftrace_caller:
+	mov.l	.Lfunction_trace_stop, r0
+	mov.l	@r0, r0
+	tst	r0, r0
+	bf	ftrace_stub
+
 	MCOUNT_ENTER()
 
 	.globl ftrace_call
@@ -70,9 +187,18 @@ ftrace_call:
 	jsr	@r6
 	 nop
 
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	bra	ftrace_graph_call
+	 nop
+#else
 	MCOUNT_LEAVE()
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
 #endif /* CONFIG_DYNAMIC_FTRACE */
 
+	.align 2
+.Lfunction_trace_stop:
+	.long	function_trace_stop
+
 /*
  * NOTE: From here on the locations of the .Lftrace_stub label and
  * ftrace_stub itself are fixed. Adding additional data here will skew
@@ -80,7 +206,6 @@ ftrace_call:
  * Place new labels either after the ftrace_stub body, or before
  * ftrace_caller. You have been warned.
  */
-	.align 2
 .Lftrace_stub:
 	.long	ftrace_stub
 
@@ -88,3 +213,98 @@ ftrace_call:
 ftrace_stub:
 	rts
 	 nop
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	.globl	ftrace_graph_caller
+ftrace_graph_caller:
+	mov.l	2f, r0
+	mov.l	@r0, r0
+	tst	r0, r0
+	bt	1f
+
+	mov.l	3f, r1
+	jmp	@r1
+	 nop
+1:
+	/*
+	 * MCOUNT_ENTER() pushed 5 registers onto the stack, so
+	 * the stack address containing our return address is
+	 * r15 + 20.
+	 */
+	mov	#20, r0
+	add	r15, r0
+	mov	r0, r4
+
+	mov.l	.Lprepare_ftrace_return, r0
+	jsr	@r0
+	 nop
+
+	MCOUNT_LEAVE()
+
+	.align 2
+2:	.long	function_trace_stop
+3:	.long	skip_trace
+.Lprepare_ftrace_return:
+	.long	prepare_ftrace_return
+
+	.globl	return_to_handler
+return_to_handler:
+	/*
+	 * Save the return values.
+	 */
+	mov.l	r0, @-r15
+	mov.l	r1, @-r15
+
+	mov	#0, r4
+
+	mov.l	.Lftrace_return_to_handler, r0
+	jsr	@r0
+	 nop
+
+	/*
+	 * The return value from ftrace_return_handler has the real
+	 * address that we should return to.
+	 */
+	lds	r0, pr
+	mov.l	@r15+, r1
+	rts
+	 mov.l	@r15+, r0
+
+
+	.align 2
+.Lftrace_return_to_handler:
+	.long	ftrace_return_to_handler
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+#endif /* CONFIG_FUNCTION_TRACER */
+
+#ifdef CONFIG_STACK_DEBUG
+	.globl	stack_panic
+stack_panic:
+	mov.l	.Ldump_stack, r0
+	jsr	@r0
+	 nop
+
+	mov.l	.Lpanic, r0
+	jsr	@r0
+	 mov.l	.Lpanic_s, r4
+
+	rts
+	 nop
+
+	.align 2
+.L_ebss:
+	.long	_ebss
+.L_init_thread_union:
+	.long	init_thread_union
+.Lpanic:
+	.long	panic
+.Lpanic_s:
+	.long	.Lpanic_str
+.Ldump_stack:
+	.long	dump_stack
+
+	.section	.rodata
+	.align 2
+.Lpanic_str:
+	.string "Stack error"
+#endif /* CONFIG_STACK_DEBUG */
diff --git a/arch/sh/mm/fault_32.c b/arch/sh/mm/fault_32.c
index 71925946f1e1..dbbdeba2cee5 100644
--- a/arch/sh/mm/fault_32.c
+++ b/arch/sh/mm/fault_32.c
@@ -2,7 +2,7 @@
  * Page fault handler for SH with an MMU.
  *
  *  Copyright (C) 1999  Niibe Yutaka
- *  Copyright (C) 2003 - 2008  Paul Mundt
+ *  Copyright (C) 2003 - 2009  Paul Mundt
  *
  *  Based on linux/arch/i386/mm/fault.c:
  *   Copyright (C) 1995  Linus Torvalds
@@ -25,18 +25,91 @@ static inline int notify_page_fault(struct pt_regs *regs, int trap)
 {
 	int ret = 0;
 
-#ifdef CONFIG_KPROBES
-	if (!user_mode(regs)) {
+	if (kprobes_built_in() && !user_mode(regs)) {
 		preempt_disable();
 		if (kprobe_running() && kprobe_fault_handler(regs, trap))
 			ret = 1;
 		preempt_enable();
 	}
-#endif
 
 	return ret;
 }
 
+static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address)
+{
+	unsigned index = pgd_index(address);
+	pgd_t *pgd_k;
+	pud_t *pud, *pud_k;
+	pmd_t *pmd, *pmd_k;
+
+	pgd += index;
+	pgd_k = init_mm.pgd + index;
+
+	if (!pgd_present(*pgd_k))
+		return NULL;
+
+	pud = pud_offset(pgd, address);
+	pud_k = pud_offset(pgd_k, address);
+	if (!pud_present(*pud_k))
+		return NULL;
+
+	pmd = pmd_offset(pud, address);
+	pmd_k = pmd_offset(pud_k, address);
+	if (!pmd_present(*pmd_k))
+		return NULL;
+
+	if (!pmd_present(*pmd))
+		set_pmd(pmd, *pmd_k);
+	else {
+		/*
+		 * The page tables are fully synchronised so there must
+		 * be another reason for the fault. Return NULL here to
+		 * signal that we have not taken care of the fault.
+		 */
+		BUG_ON(pmd_page(*pmd) != pmd_page(*pmd_k));
+		return NULL;
+	}
+
+	return pmd_k;
+}
+
+/*
+ * Handle a fault on the vmalloc or module mapping area
+ */
+static noinline int vmalloc_fault(unsigned long address)
+{
+	pgd_t *pgd_k;
+	pmd_t *pmd_k;
+	pte_t *pte_k;
+
+	/* Make sure we are in vmalloc area: */
+	if (!(address >= VMALLOC_START && address < VMALLOC_END))
+		return -1;
+
+	/*
+	 * Synchronize this task's top level page-table
+	 * with the 'reference' page table.
+	 *
+	 * Do _not_ use "current" here. We might be inside
+	 * an interrupt in the middle of a task switch..
+	 */
+	pgd_k = get_TTB();
+	pmd_k = vmalloc_sync_one(pgd_k, address);
+	if (!pmd_k)
+		return -1;
+
+	pte_k = pte_offset_kernel(pmd_k, address);
+	if (!pte_present(*pte_k))
+		return -1;
+
+	return 0;
+}
+
+static int fault_in_kernel_space(unsigned long address)
+{
+	return address >= TASK_SIZE;
+}
+
 /*
  * This routine handles page faults.  It determines the address,
  * and the problem, and then passes it off to one of the appropriate
@@ -46,6 +119,7 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
 					unsigned long writeaccess,
 					unsigned long address)
 {
+	unsigned long vec;
 	struct task_struct *tsk;
 	struct mm_struct *mm;
 	struct vm_area_struct * vma;
@@ -53,59 +127,30 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
 	int fault;
 	siginfo_t info;
 
-	/*
-	 * We don't bother with any notifier callbacks here, as they are
-	 * all handled through the __do_page_fault() fast-path.
-	 */
-
 	tsk = current;
+	mm = tsk->mm;
 	si_code = SEGV_MAPERR;
+	vec = lookup_exception_vector();
 
-	if (unlikely(address >= TASK_SIZE)) {
-		/*
-		 * Synchronize this task's top level page-table
-		 * with the 'reference' page table.
-		 *
-		 * Do _not_ use "tsk" here. We might be inside
-		 * an interrupt in the middle of a task switch..
-		 */
-		int offset = pgd_index(address);
-		pgd_t *pgd, *pgd_k;
-		pud_t *pud, *pud_k;
-		pmd_t *pmd, *pmd_k;
-
-		pgd = get_TTB() + offset;
-		pgd_k = swapper_pg_dir + offset;
-
-		if (!pgd_present(*pgd)) {
-			if (!pgd_present(*pgd_k))
-				goto bad_area_nosemaphore;
-			set_pgd(pgd, *pgd_k);
+	/*
+	 * We fault-in kernel-space virtual memory on-demand. The
+	 * 'reference' page table is init_mm.pgd.
+	 *
+	 * NOTE! We MUST NOT take any locks for this case. We may
+	 * be in an interrupt or a critical region, and should
+	 * only copy the information from the master page table,
+	 * nothing more.
+	 */
+	if (unlikely(fault_in_kernel_space(address))) {
+		if (vmalloc_fault(address) >= 0)
 			return;
-		}
-
-		pud = pud_offset(pgd, address);
-		pud_k = pud_offset(pgd_k, address);
-
-		if (!pud_present(*pud)) {
-			if (!pud_present(*pud_k))
-				goto bad_area_nosemaphore;
-			set_pud(pud, *pud_k);
+		if (notify_page_fault(regs, vec))
 			return;
-		}
 
-		pmd = pmd_offset(pud, address);
-		pmd_k = pmd_offset(pud_k, address);
-		if (pmd_present(*pmd) || !pmd_present(*pmd_k))
-			goto bad_area_nosemaphore;
-		set_pmd(pmd, *pmd_k);
-
-		return;
+		goto bad_area_nosemaphore;
 	}
 
-	mm = tsk->mm;
-
-	if (unlikely(notify_page_fault(regs, lookup_exception_vector())))
+	if (unlikely(notify_page_fault(regs, vec)))
 		return;
 
 	/* Only enable interrupts if they were on before the fault */
@@ -115,8 +160,8 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
 	perf_swcounter_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address);
 
 	/*
-	 * If we're in an interrupt or have no user
-	 * context, we must not take the fault..
+	 * If we're in an interrupt, have no user context or are running
+	 * in an atomic region then we must not take the fault:
 	 */
 	if (in_atomic() || !mm)
 		goto no_context;
@@ -132,10 +177,11 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
 		goto bad_area;
 	if (expand_stack(vma, address))
 		goto bad_area;
-/*
- * Ok, we have a good vm_area for this memory access, so
- * we can handle it..
- */
+
+	/*
+	 * Ok, we have a good vm_area for this memory access, so
+	 * we can handle it..
+	 */
 good_area:
 	si_code = SEGV_ACCERR;
 	if (writeaccess) {
@@ -173,10 +219,10 @@ survive:
 	up_read(&mm->mmap_sem);
 	return;
 
-/*
- * Something tried to access memory that isn't in our memory map..
- * Fix it, but check if it's kernel or user first..
- */
+	/*
+	 * Something tried to access memory that isn't in our memory map..
+	 * Fix it, but check if it's kernel or user first..
+	 */
 bad_area:
 	up_read(&mm->mmap_sem);
 
diff --git a/arch/sh/mm/ioremap_64.c b/arch/sh/mm/ioremap_64.c
index 828c8597219d..b16843d02b76 100644
--- a/arch/sh/mm/ioremap_64.c
+++ b/arch/sh/mm/ioremap_64.c
@@ -94,7 +94,6 @@ static struct resource *shmedia_find_resource(struct resource *root,
 static void __iomem *shmedia_alloc_io(unsigned long phys, unsigned long size,
 				      const char *name, unsigned long flags)
 {
-	static int printed_full;
 	struct xresource *xres;
 	struct resource *res;
 	char *tack;
@@ -108,11 +107,8 @@ static void __iomem *shmedia_alloc_io(unsigned long phys, unsigned long size,
 		tack = xres->xname;
 		res = &xres->xres;
 	} else {
-		if (!printed_full) {
-			printk(KERN_NOTICE "%s: done with statics, "
+		printk_once(KERN_NOTICE "%s: done with statics, "
 			       "switching to kmalloc\n", __func__);
-			printed_full = 1;
-		}
 		tlen = strlen(name);
 		tack = kmalloc(sizeof(struct resource) + tlen + 1, GFP_KERNEL);
 		if (!tack)
diff --git a/arch/sh/mm/numa.c b/arch/sh/mm/numa.c
index 095d93bec7cd..9b784fdb947c 100644
--- a/arch/sh/mm/numa.c
+++ b/arch/sh/mm/numa.c
@@ -9,6 +9,7 @@
  */
 #include <linux/module.h>
 #include <linux/bootmem.h>
+#include <linux/lmb.h>
 #include <linux/mm.h>
 #include <linux/numa.h>
 #include <linux/pfn.h>
@@ -26,6 +27,15 @@ EXPORT_SYMBOL_GPL(node_data);
 void __init setup_memory(void)
 {
 	unsigned long free_pfn = PFN_UP(__pa(_end));
+	u64 base = min_low_pfn << PAGE_SHIFT;
+	u64 size = (max_low_pfn << PAGE_SHIFT) - min_low_pfn;
+
+	lmb_add(base, size);
+
+	/* Reserve the LMB regions used by the kernel, initrd, etc.. */
+	lmb_reserve(__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET,
+		    (PFN_PHYS(free_pfn) + PAGE_SIZE - 1) -
+		    (__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET));
 
 	/*
 	 * Node 0 sets up its pgdat at the first available pfn,
@@ -45,24 +55,23 @@ void __init setup_memory(void)
 
 void __init setup_bootmem_node(int nid, unsigned long start, unsigned long end)
 {
-	unsigned long bootmap_pages, bootmap_start, bootmap_size;
-	unsigned long start_pfn, free_pfn, end_pfn;
+	unsigned long bootmap_pages;
+	unsigned long start_pfn, end_pfn;
+	unsigned long bootmem_paddr;
 
 	/* Don't allow bogus node assignment */
 	BUG_ON(nid > MAX_NUMNODES || nid == 0);
 
-	/*
-	 * The free pfn starts at the beginning of the range, and is
-	 * advanced as necessary for pgdat and node map allocations.
-	 */
-	free_pfn = start_pfn = start >> PAGE_SHIFT;
+	start_pfn = start >> PAGE_SHIFT;
 	end_pfn = end >> PAGE_SHIFT;
 
+	lmb_add(start, end - start);
+
 	__add_active_range(nid, start_pfn, end_pfn);
 
 	/* Node-local pgdat */
-	NODE_DATA(nid) = pfn_to_kaddr(free_pfn);
-	free_pfn += PFN_UP(sizeof(struct pglist_data));
+	NODE_DATA(nid) = __va(lmb_alloc_base(sizeof(struct pglist_data),
+					     SMP_CACHE_BYTES, end_pfn));
 	memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
 
 	NODE_DATA(nid)->bdata = &bootmem_node_data[nid];
@@ -71,16 +80,17 @@ void __init setup_bootmem_node(int nid, unsigned long start, unsigned long end)
 
 	/* Node-local bootmap */
 	bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn);
-	bootmap_start = (unsigned long)pfn_to_kaddr(free_pfn);
-	bootmap_size = init_bootmem_node(NODE_DATA(nid), free_pfn, start_pfn,
-				    end_pfn);
+	bootmem_paddr = lmb_alloc_base(bootmap_pages << PAGE_SHIFT,
+				       PAGE_SIZE, end_pfn);
+	init_bootmem_node(NODE_DATA(nid), bootmem_paddr >> PAGE_SHIFT,
+			  start_pfn, end_pfn);
 
 	free_bootmem_with_active_regions(nid, end_pfn);
 
 	/* Reserve the pgdat and bootmap space with the bootmem allocator */
 	reserve_bootmem_node(NODE_DATA(nid), start_pfn << PAGE_SHIFT,
 			     sizeof(struct pglist_data), BOOTMEM_DEFAULT);
-	reserve_bootmem_node(NODE_DATA(nid), free_pfn << PAGE_SHIFT,
+	reserve_bootmem_node(NODE_DATA(nid), bootmem_paddr,
 			     bootmap_pages << PAGE_SHIFT, BOOTMEM_DEFAULT);
 
 	/* It's up */
diff --git a/arch/sh/oprofile/backtrace.c b/arch/sh/oprofile/backtrace.c
index 9499a2914f89..2bc74de23f08 100644
--- a/arch/sh/oprofile/backtrace.c
+++ b/arch/sh/oprofile/backtrace.c
@@ -17,9 +17,43 @@
 #include <linux/sched.h>
 #include <linux/kallsyms.h>
 #include <linux/mm.h>
+#include <asm/unwinder.h>
 #include <asm/ptrace.h>
 #include <asm/uaccess.h>
 #include <asm/sections.h>
+#include <asm/stacktrace.h>
+
+static void backtrace_warning_symbol(void *data, char *msg,
+				     unsigned long symbol)
+{
+	/* Ignore warnings */
+}
+
+static void backtrace_warning(void *data, char *msg)
+{
+	/* Ignore warnings */
+}
+
+static int backtrace_stack(void *data, char *name)
+{
+	/* Yes, we want all stacks */
+	return 0;
+}
+
+static void backtrace_address(void *data, unsigned long addr, int reliable)
+{
+	unsigned int *depth = data;
+
+	if ((*depth)--)
+		oprofile_add_trace(addr);
+}
+
+static struct stacktrace_ops backtrace_ops = {
+	.warning = backtrace_warning,
+	.warning_symbol = backtrace_warning_symbol,
+	.stack = backtrace_stack,
+	.address = backtrace_address,
+};
 
 /* Limit to stop backtracing too far. */
 static int backtrace_limit = 20;
@@ -47,50 +81,6 @@ user_backtrace(unsigned long *stackaddr, struct pt_regs *regs)
 	return stackaddr;
 }
 
-/*
- * |             | /\ Higher addresses
- * |             |
- * --------------- stack base (address of current_thread_info)
- * | thread info |
- * .             .
- * |    stack    |
- * --------------- saved regs->regs[15] value if valid
- * .             .
- * --------------- struct pt_regs stored on stack (struct pt_regs *)
- * |             |
- * .             .
- * |             |
- * --------------- ???
- * |             |
- * |             | \/ Lower addresses
- *
- * Thus, &pt_regs <-> stack base restricts the valid(ish) fp values
- */
-static int valid_kernel_stack(unsigned long *stackaddr, struct pt_regs *regs)
-{
-	unsigned long stack = (unsigned long)regs;
-	unsigned long stack_base = (stack & ~(THREAD_SIZE - 1)) + THREAD_SIZE;
-
-	return ((unsigned long)stackaddr > stack) && ((unsigned long)stackaddr < stack_base);
-}
-
-static unsigned long *
-kernel_backtrace(unsigned long *stackaddr, struct pt_regs *regs)
-{
-	unsigned long addr;
-
-	/*
-	 * If not a valid kernel address, keep going till we find one
-	 * or the SP stops being a valid address.
-	 */
-	do {
-		addr = *stackaddr++;
-		oprofile_add_trace(addr);
-	} while (valid_kernel_stack(stackaddr, regs));
-
-	return stackaddr;
-}
-
 void sh_backtrace(struct pt_regs * const regs, unsigned int depth)
 {
 	unsigned long *stackaddr;
@@ -103,9 +93,9 @@ void sh_backtrace(struct pt_regs * const regs, unsigned int depth)
 
 	stackaddr = (unsigned long *)regs->regs[15];
 	if (!user_mode(regs)) {
-		while (depth-- && valid_kernel_stack(stackaddr, regs))
-			stackaddr = kernel_backtrace(stackaddr, regs);
-
+		if (depth)
+			unwind_stack(NULL, regs, stackaddr,
+				     &backtrace_ops, &depth);
 		return;
 	}
 
diff --git a/arch/sh/tools/mach-types b/arch/sh/tools/mach-types
index fec3a53b8650..09eef360dde1 100644
--- a/arch/sh/tools/mach-types
+++ b/arch/sh/tools/mach-types
@@ -56,3 +56,4 @@ SH7785LCR		SH_SH7785LCR
 URQUELL			SH_URQUELL
 ESPT			SH_ESPT
 POLARIS			SH_POLARIS
+KFR2R09			SH_KFR2R09
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c
index 8e2feb563347..4cbb87ad070a 100644
--- a/drivers/serial/sh-sci.c
+++ b/drivers/serial/sh-sci.c
@@ -662,10 +662,11 @@ static irqreturn_t sci_rx_interrupt(int irq, void *port)
 static irqreturn_t sci_tx_interrupt(int irq, void *ptr)
 {
 	struct uart_port *port = ptr;
+	unsigned long flags;
 
-	spin_lock_irq(&port->lock);
+	spin_lock_irqsave(&port->lock, flags);
 	sci_transmit_chars(port);
-	spin_unlock_irq(&port->lock);
+	spin_unlock_irqrestore(&port->lock, flags);
 
 	return IRQ_HANDLED;
 }
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 7f8e83a954ac..b7f10bc25c2c 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -360,16 +360,6 @@ config USB_M66592
 	default USB_GADGET
 	select USB_GADGET_SELECTED
 
-config SUPERH_BUILT_IN_M66592
-	boolean "Enable SuperH built-in USB like the M66592"
-	depends on USB_GADGET_M66592 && CPU_SUBTYPE_SH7722
-	help
-	   SH7722 has USB like the M66592.
-
-	   The transfer rate is very slow when use "Ethernet Gadget".
-	   However, this problem is improved if change a value of
-	   NET_IP_ALIGN to 4.
-
 #
 # Controllers available only in discrete form (and all PCI controllers)
 #
diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c
index 43dcf9e1af6b..a61c70caff12 100644
--- a/drivers/usb/gadget/m66592-udc.c
+++ b/drivers/usb/gadget/m66592-udc.c
@@ -31,38 +31,12 @@
 
 #include "m66592-udc.h"
 
-
 MODULE_DESCRIPTION("M66592 USB gadget driver");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Yoshihiro Shimoda");
 MODULE_ALIAS("platform:m66592_udc");
 
-#define DRIVER_VERSION	"18 Oct 2007"
-
-/* module parameters */
-#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
-static unsigned short endian = M66592_LITTLE;
-module_param(endian, ushort, 0644);
-MODULE_PARM_DESC(endian, "data endian: big=0, little=0 (default=0)");
-#else
-static unsigned short clock = M66592_XTAL24;
-module_param(clock, ushort, 0644);
-MODULE_PARM_DESC(clock, "input clock: 48MHz=32768, 24MHz=16384, 12MHz=0 "
-		"(default=16384)");
-
-static unsigned short vif = M66592_LDRV;
-module_param(vif, ushort, 0644);
-MODULE_PARM_DESC(vif, "input VIF: 3.3V=32768, 1.5V=0 (default=32768)");
-
-static unsigned short endian;
-module_param(endian, ushort, 0644);
-MODULE_PARM_DESC(endian, "data endian: big=256, little=0 (default=0)");
-
-static unsigned short irq_sense = M66592_INTL;
-module_param(irq_sense, ushort, 0644);
-MODULE_PARM_DESC(irq_sense, "IRQ sense: low level=2, falling edge=0 "
-		"(default=2)");
-#endif
+#define DRIVER_VERSION	"21 July 2009"
 
 static const char udc_name[] = "m66592_udc";
 static const char *m66592_ep_name[] = {
@@ -244,6 +218,7 @@ static inline int get_buffer_size(struct m66592 *m66592, u16 pipenum)
 static inline void pipe_change(struct m66592 *m66592, u16 pipenum)
 {
 	struct m66592_ep *ep = m66592->pipenum2ep[pipenum];
+	unsigned short mbw;
 
 	if (ep->use_dma)
 		return;
@@ -252,7 +227,12 @@ static inline void pipe_change(struct m66592 *m66592, u16 pipenum)
 
 	ndelay(450);
 
-	m66592_bset(m66592, M66592_MBW, ep->fifosel);
+	if (m66592->pdata->on_chip)
+		mbw = M66592_MBW_32;
+	else
+		mbw = M66592_MBW_16;
+
+	m66592_bset(m66592, mbw, ep->fifosel);
 }
 
 static int pipe_buffer_setting(struct m66592 *m66592,
@@ -276,24 +256,27 @@ static int pipe_buffer_setting(struct m66592 *m66592,
 		buf_bsize = 0;
 		break;
 	case M66592_BULK:
-		bufnum = m66592->bi_bufnum +
-			 (info->pipe - M66592_BASE_PIPENUM_BULK) * 16;
-		m66592->bi_bufnum += 16;
+		/* isochronous pipes may be used as bulk pipes */
+		if (info->pipe > M66592_BASE_PIPENUM_BULK)
+			bufnum = info->pipe - M66592_BASE_PIPENUM_BULK;
+		else
+			bufnum = info->pipe - M66592_BASE_PIPENUM_ISOC;
+
+		bufnum = M66592_BASE_BUFNUM + (bufnum * 16);
 		buf_bsize = 7;
 		pipecfg |= M66592_DBLB;
 		if (!info->dir_in)
 			pipecfg |= M66592_SHTNAK;
 		break;
 	case M66592_ISO:
-		bufnum = m66592->bi_bufnum +
+		bufnum = M66592_BASE_BUFNUM +
 			 (info->pipe - M66592_BASE_PIPENUM_ISOC) * 16;
-		m66592->bi_bufnum += 16;
 		buf_bsize = 7;
 		break;
 	}
-	if (m66592->bi_bufnum > M66592_MAX_BUFNUM) {
-		pr_err("m66592 pipe memory is insufficient(%d)\n",
-				m66592->bi_bufnum);
+
+	if (buf_bsize && ((bufnum + 16) >= M66592_MAX_BUFNUM)) {
+		pr_err("m66592 pipe memory is insufficient\n");
 		return -ENOMEM;
 	}
 
@@ -313,17 +296,6 @@ static void pipe_buffer_release(struct m66592 *m66592,
 	if (info->pipe == 0)
 		return;
 
-	switch (info->type) {
-	case M66592_BULK:
-		if (is_bulk_pipe(info->pipe))
-			m66592->bi_bufnum -= 16;
-		break;
-	case M66592_ISO:
-		if (is_isoc_pipe(info->pipe))
-			m66592->bi_bufnum -= 16;
-		break;
-	}
-
 	if (is_bulk_pipe(info->pipe)) {
 		m66592->bulk--;
 	} else if (is_interrupt_pipe(info->pipe))
@@ -340,6 +312,7 @@ static void pipe_buffer_release(struct m66592 *m66592,
 static void pipe_initialize(struct m66592_ep *ep)
 {
 	struct m66592 *m66592 = ep->m66592;
+	unsigned short mbw;
 
 	m66592_mdfy(m66592, 0, M66592_CURPIPE, ep->fifosel);
 
@@ -351,7 +324,12 @@ static void pipe_initialize(struct m66592_ep *ep)
 
 		ndelay(450);
 
-		m66592_bset(m66592, M66592_MBW, ep->fifosel);
+		if (m66592->pdata->on_chip)
+			mbw = M66592_MBW_32;
+		else
+			mbw = M66592_MBW_16;
+
+		m66592_bset(m66592, mbw, ep->fifosel);
 	}
 }
 
@@ -367,15 +345,13 @@ static void m66592_ep_setting(struct m66592 *m66592, struct m66592_ep *ep,
 			ep->fifosel = M66592_D0FIFOSEL;
 			ep->fifoctr = M66592_D0FIFOCTR;
 			ep->fifotrn = M66592_D0FIFOTRN;
-#if !defined(CONFIG_SUPERH_BUILT_IN_M66592)
-		} else if (m66592->num_dma == 1) {
+		} else if (!m66592->pdata->on_chip && m66592->num_dma == 1) {
 			m66592->num_dma++;
 			ep->use_dma = 1;
 			ep->fifoaddr = M66592_D1FIFO;
 			ep->fifosel = M66592_D1FIFOSEL;
 			ep->fifoctr = M66592_D1FIFOCTR;
 			ep->fifotrn = M66592_D1FIFOTRN;
-#endif
 		} else {
 			ep->use_dma = 0;
 			ep->fifoaddr = M66592_CFIFO;
@@ -620,76 +596,120 @@ static void start_ep0(struct m66592_ep *ep, struct m66592_request *req)
 	}
 }
 
-#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
 static void init_controller(struct m66592 *m66592)
 {
-	m66592_bset(m66592, M66592_HSE, M66592_SYSCFG);		/* High spd */
-	m66592_bclr(m66592, M66592_USBE, M66592_SYSCFG);
-	m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG);
-	m66592_bset(m66592, M66592_USBE, M66592_SYSCFG);
+	unsigned int endian;
 
-	/* This is a workaound for SH7722 2nd cut */
-	m66592_bset(m66592, 0x8000, M66592_DVSTCTR);
-	m66592_bset(m66592, 0x1000, M66592_TESTMODE);
-	m66592_bclr(m66592, 0x8000, M66592_DVSTCTR);
+	if (m66592->pdata->on_chip) {
+		if (m66592->pdata->endian)
+			endian = 0; /* big endian */
+		else
+			endian = M66592_LITTLE; /* little endian */
 
-	m66592_bset(m66592, M66592_INTL, M66592_INTENB1);
+		m66592_bset(m66592, M66592_HSE, M66592_SYSCFG);	/* High spd */
+		m66592_bclr(m66592, M66592_USBE, M66592_SYSCFG);
+		m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG);
+		m66592_bset(m66592, M66592_USBE, M66592_SYSCFG);
 
-	m66592_write(m66592, 0, M66592_CFBCFG);
-	m66592_write(m66592, 0, M66592_D0FBCFG);
-	m66592_bset(m66592, endian, M66592_CFBCFG);
-	m66592_bset(m66592, endian, M66592_D0FBCFG);
+		/* This is a workaound for SH7722 2nd cut */
+		m66592_bset(m66592, 0x8000, M66592_DVSTCTR);
+		m66592_bset(m66592, 0x1000, M66592_TESTMODE);
+		m66592_bclr(m66592, 0x8000, M66592_DVSTCTR);
+
+		m66592_bset(m66592, M66592_INTL, M66592_INTENB1);
+
+		m66592_write(m66592, 0, M66592_CFBCFG);
+		m66592_write(m66592, 0, M66592_D0FBCFG);
+		m66592_bset(m66592, endian, M66592_CFBCFG);
+		m66592_bset(m66592, endian, M66592_D0FBCFG);
+	} else {
+		unsigned int clock, vif, irq_sense;
+
+		if (m66592->pdata->endian)
+			endian = M66592_BIGEND; /* big endian */
+		else
+			endian = 0; /* little endian */
+
+		if (m66592->pdata->vif)
+			vif = M66592_LDRV; /* 3.3v */
+		else
+			vif = 0; /* 1.5v */
+
+		switch (m66592->pdata->xtal) {
+		case M66592_PLATDATA_XTAL_12MHZ:
+			clock = M66592_XTAL12;
+			break;
+		case M66592_PLATDATA_XTAL_24MHZ:
+			clock = M66592_XTAL24;
+			break;
+		case M66592_PLATDATA_XTAL_48MHZ:
+			clock = M66592_XTAL48;
+			break;
+		default:
+			pr_warning("m66592-udc: xtal configuration error\n");
+			clock = 0;
+		}
+
+		switch (m66592->irq_trigger) {
+		case IRQF_TRIGGER_LOW:
+			irq_sense = M66592_INTL;
+			break;
+		case IRQF_TRIGGER_FALLING:
+			irq_sense = 0;
+			break;
+		default:
+			pr_warning("m66592-udc: irq trigger config error\n");
+			irq_sense = 0;
+		}
+
+		m66592_bset(m66592,
+			    (vif & M66592_LDRV) | (endian & M66592_BIGEND),
+			    M66592_PINCFG);
+		m66592_bset(m66592, M66592_HSE, M66592_SYSCFG);	/* High spd */
+		m66592_mdfy(m66592, clock & M66592_XTAL, M66592_XTAL,
+			    M66592_SYSCFG);
+		m66592_bclr(m66592, M66592_USBE, M66592_SYSCFG);
+		m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG);
+		m66592_bset(m66592, M66592_USBE, M66592_SYSCFG);
+
+		m66592_bset(m66592, M66592_XCKE, M66592_SYSCFG);
+
+		msleep(3);
+
+		m66592_bset(m66592, M66592_RCKE | M66592_PLLC, M66592_SYSCFG);
+
+		msleep(1);
+
+		m66592_bset(m66592, M66592_SCKE, M66592_SYSCFG);
+
+		m66592_bset(m66592, irq_sense & M66592_INTL, M66592_INTENB1);
+		m66592_write(m66592, M66592_BURST | M66592_CPU_ADR_RD_WR,
+			     M66592_DMA0CFG);
+	}
 }
-#else	/* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */
-static void init_controller(struct m66592 *m66592)
-{
-	m66592_bset(m66592, (vif & M66592_LDRV) | (endian & M66592_BIGEND),
-			M66592_PINCFG);
-	m66592_bset(m66592, M66592_HSE, M66592_SYSCFG);		/* High spd */
-	m66592_mdfy(m66592, clock & M66592_XTAL, M66592_XTAL, M66592_SYSCFG);
-
-	m66592_bclr(m66592, M66592_USBE, M66592_SYSCFG);
-	m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG);
-	m66592_bset(m66592, M66592_USBE, M66592_SYSCFG);
-
-	m66592_bset(m66592, M66592_XCKE, M66592_SYSCFG);
-
-	msleep(3);
-
-	m66592_bset(m66592, M66592_RCKE | M66592_PLLC, M66592_SYSCFG);
-
-	msleep(1);
-
-	m66592_bset(m66592, M66592_SCKE, M66592_SYSCFG);
-
-	m66592_bset(m66592, irq_sense & M66592_INTL, M66592_INTENB1);
-	m66592_write(m66592, M66592_BURST | M66592_CPU_ADR_RD_WR,
-			M66592_DMA0CFG);
-}
-#endif	/* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */
 
 static void disable_controller(struct m66592 *m66592)
 {
-#if !defined(CONFIG_SUPERH_BUILT_IN_M66592)
-	m66592_bclr(m66592, M66592_SCKE, M66592_SYSCFG);
-	udelay(1);
-	m66592_bclr(m66592, M66592_PLLC, M66592_SYSCFG);
-	udelay(1);
-	m66592_bclr(m66592, M66592_RCKE, M66592_SYSCFG);
-	udelay(1);
-	m66592_bclr(m66592, M66592_XCKE, M66592_SYSCFG);
-#endif
+	if (!m66592->pdata->on_chip) {
+		m66592_bclr(m66592, M66592_SCKE, M66592_SYSCFG);
+		udelay(1);
+		m66592_bclr(m66592, M66592_PLLC, M66592_SYSCFG);
+		udelay(1);
+		m66592_bclr(m66592, M66592_RCKE, M66592_SYSCFG);
+		udelay(1);
+		m66592_bclr(m66592, M66592_XCKE, M66592_SYSCFG);
+	}
 }
 
 static void m66592_start_xclock(struct m66592 *m66592)
 {
-#if !defined(CONFIG_SUPERH_BUILT_IN_M66592)
 	u16 tmp;
 
-	tmp = m66592_read(m66592, M66592_SYSCFG);
-	if (!(tmp & M66592_XCKE))
-		m66592_bset(m66592, M66592_XCKE, M66592_SYSCFG);
-#endif
+	if (!m66592->pdata->on_chip) {
+		tmp = m66592_read(m66592, M66592_SYSCFG);
+		if (!(tmp & M66592_XCKE))
+			m66592_bset(m66592, M66592_XCKE, M66592_SYSCFG);
+	}
 }
 
 /*-------------------------------------------------------------------------*/
@@ -1177,8 +1197,7 @@ static irqreturn_t m66592_irq(int irq, void *_m66592)
 	intsts0 = m66592_read(m66592, M66592_INTSTS0);
 	intenb0 = m66592_read(m66592, M66592_INTENB0);
 
-#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
-	if (!intsts0 && !intenb0) {
+	if (m66592->pdata->on_chip && !intsts0 && !intenb0) {
 		/*
 		 * When USB clock stops, it cannot read register. Even if a
 		 * clock stops, the interrupt occurs. So this driver turn on
@@ -1188,7 +1207,6 @@ static irqreturn_t m66592_irq(int irq, void *_m66592)
 		intsts0 = m66592_read(m66592, M66592_INTSTS0);
 		intenb0 = m66592_read(m66592, M66592_INTENB0);
 	}
-#endif
 
 	savepipe = m66592_read(m66592, M66592_CFIFOSEL);
 
@@ -1534,9 +1552,11 @@ static int __exit m66592_remove(struct platform_device *pdev)
 	iounmap(m66592->reg);
 	free_irq(platform_get_irq(pdev, 0), m66592);
 	m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
-#if defined(CONFIG_SUPERH_BUILT_IN_M66592) && defined(CONFIG_HAVE_CLK)
-	clk_disable(m66592->clk);
-	clk_put(m66592->clk);
+#ifdef CONFIG_HAVE_CLK
+	if (m66592->pdata->on_chip) {
+		clk_disable(m66592->clk);
+		clk_put(m66592->clk);
+	}
 #endif
 	kfree(m66592);
 	return 0;
@@ -1548,11 +1568,10 @@ static void nop_completion(struct usb_ep *ep, struct usb_request *r)
 
 static int __init m66592_probe(struct platform_device *pdev)
 {
-	struct resource *res;
-	int irq;
+	struct resource *res, *ires;
 	void __iomem *reg = NULL;
 	struct m66592 *m66592 = NULL;
-#if defined(CONFIG_SUPERH_BUILT_IN_M66592) && defined(CONFIG_HAVE_CLK)
+#ifdef CONFIG_HAVE_CLK
 	char clk_name[8];
 #endif
 	int ret = 0;
@@ -1565,10 +1584,11 @@ static int __init m66592_probe(struct platform_device *pdev)
 		goto clean_up;
 	}
 
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0) {
+	ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!ires) {
 		ret = -ENODEV;
-		pr_err("platform_get_irq error.\n");
+		dev_err(&pdev->dev,
+			"platform_get_resource IORESOURCE_IRQ error.\n");
 		goto clean_up;
 	}
 
@@ -1579,6 +1599,12 @@ static int __init m66592_probe(struct platform_device *pdev)
 		goto clean_up;
 	}
 
+	if (pdev->dev.platform_data == NULL) {
+		dev_err(&pdev->dev, "no platform data\n");
+		ret = -ENODEV;
+		goto clean_up;
+	}
+
 	/* initialize ucd */
 	m66592 = kzalloc(sizeof(struct m66592), GFP_KERNEL);
 	if (m66592 == NULL) {
@@ -1586,6 +1612,9 @@ static int __init m66592_probe(struct platform_device *pdev)
 		goto clean_up;
 	}
 
+	m66592->pdata = pdev->dev.platform_data;
+	m66592->irq_trigger = ires->flags & IRQF_TRIGGER_MASK;
+
 	spin_lock_init(&m66592->lock);
 	dev_set_drvdata(&pdev->dev, m66592);
 
@@ -1603,24 +1632,25 @@ static int __init m66592_probe(struct platform_device *pdev)
 	m66592->timer.data = (unsigned long)m66592;
 	m66592->reg = reg;
 
-	m66592->bi_bufnum = M66592_BASE_BUFNUM;
-
-	ret = request_irq(irq, m66592_irq, IRQF_DISABLED | IRQF_SHARED,
+	ret = request_irq(ires->start, m66592_irq, IRQF_DISABLED | IRQF_SHARED,
 			udc_name, m66592);
 	if (ret < 0) {
 		pr_err("request_irq error (%d)\n", ret);
 		goto clean_up;
 	}
 
-#if defined(CONFIG_SUPERH_BUILT_IN_M66592) && defined(CONFIG_HAVE_CLK)
-	snprintf(clk_name, sizeof(clk_name), "usbf%d", pdev->id);
-	m66592->clk = clk_get(&pdev->dev, clk_name);
-	if (IS_ERR(m66592->clk)) {
-		dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name);
-		ret = PTR_ERR(m66592->clk);
-		goto clean_up2;
+#ifdef CONFIG_HAVE_CLK
+	if (m66592->pdata->on_chip) {
+		snprintf(clk_name, sizeof(clk_name), "usbf%d", pdev->id);
+		m66592->clk = clk_get(&pdev->dev, clk_name);
+		if (IS_ERR(m66592->clk)) {
+			dev_err(&pdev->dev, "cannot get clock \"%s\"\n",
+				clk_name);
+			ret = PTR_ERR(m66592->clk);
+			goto clean_up2;
+		}
+		clk_enable(m66592->clk);
 	}
-	clk_enable(m66592->clk);
 #endif
 	INIT_LIST_HEAD(&m66592->gadget.ep_list);
 	m66592->gadget.ep0 = &m66592->ep[0].ep;
@@ -1662,12 +1692,14 @@ static int __init m66592_probe(struct platform_device *pdev)
 	return 0;
 
 clean_up3:
-#if defined(CONFIG_SUPERH_BUILT_IN_M66592) && defined(CONFIG_HAVE_CLK)
-	clk_disable(m66592->clk);
-	clk_put(m66592->clk);
+#ifdef CONFIG_HAVE_CLK
+	if (m66592->pdata->on_chip) {
+		clk_disable(m66592->clk);
+		clk_put(m66592->clk);
+	}
 clean_up2:
 #endif
-	free_irq(irq, m66592);
+	free_irq(ires->start, m66592);
 clean_up:
 	if (m66592) {
 		if (m66592->ep0_req)
diff --git a/drivers/usb/gadget/m66592-udc.h b/drivers/usb/gadget/m66592-udc.h
index 286ce07e7960..8b960deed680 100644
--- a/drivers/usb/gadget/m66592-udc.h
+++ b/drivers/usb/gadget/m66592-udc.h
@@ -23,10 +23,12 @@
 #ifndef __M66592_UDC_H__
 #define __M66592_UDC_H__
 
-#if defined(CONFIG_SUPERH_BUILT_IN_M66592) && defined(CONFIG_HAVE_CLK)
+#ifdef CONFIG_HAVE_CLK
 #include <linux/clk.h>
 #endif
 
+#include <linux/usb/m66592.h>
+
 #define M66592_SYSCFG		0x00
 #define M66592_XTAL		0xC000	/* b15-14: Crystal selection */
 #define   M66592_XTAL48		 0x8000		/* 48MHz */
@@ -76,11 +78,11 @@
 #define   M66592_P_TST_J	 0x0001		/* PERI TEST J */
 #define   M66592_P_TST_NORMAL	 0x0000		/* PERI Normal Mode */
 
-#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
+/* built-in registers */
 #define M66592_CFBCFG		0x0A
 #define M66592_D0FBCFG		0x0C
 #define M66592_LITTLE		0x0100	/* b8: Little endian mode */
-#else
+/* external chip case */
 #define M66592_PINCFG		0x0A
 #define M66592_LDRV		0x8000	/* b15: Drive Current Adjust */
 #define M66592_BIGEND		0x0100	/* b8: Big endian mode */
@@ -100,8 +102,8 @@
 #define M66592_PKTM		0x0020	/* b5: Packet mode */
 #define M66592_DENDE		0x0010	/* b4: Dend enable */
 #define M66592_OBUS		0x0004	/* b2: OUTbus mode */
-#endif	/* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */
 
+/* common case */
 #define M66592_CFIFO		0x10
 #define M66592_D0FIFO		0x14
 #define M66592_D1FIFO		0x18
@@ -113,13 +115,9 @@
 #define M66592_REW		0x4000	/* b14: Buffer rewind */
 #define M66592_DCLRM		0x2000	/* b13: DMA buffer clear mode */
 #define M66592_DREQE		0x1000	/* b12: DREQ output enable */
-#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
-#define M66592_MBW		0x0800	/* b11: Maximum bit width for FIFO */
-#else
-#define M66592_MBW		0x0400	/* b10: Maximum bit width for FIFO */
-#define   M66592_MBW_8		 0x0000   /*  8bit */
-#define   M66592_MBW_16		 0x0400   /* 16bit */
-#endif	/* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */
+#define M66592_MBW_8		0x0000   /*  8bit */
+#define M66592_MBW_16		0x0400   /* 16bit */
+#define M66592_MBW_32		0x0800   /* 32bit */
 #define M66592_TRENB		0x0200	/* b9: Transaction counter enable */
 #define M66592_TRCLR		0x0100	/* b8: Transaction counter clear */
 #define M66592_DEZPM		0x0080	/* b7: Zero-length packet mode */
@@ -480,9 +478,11 @@ struct m66592_ep {
 struct m66592 {
 	spinlock_t		lock;
 	void __iomem		*reg;
-#if defined(CONFIG_SUPERH_BUILT_IN_M66592) && defined(CONFIG_HAVE_CLK)
+#ifdef CONFIG_HAVE_CLK
 	struct clk *clk;
 #endif
+	struct m66592_platdata	*pdata;
+	unsigned long		irq_trigger;
 
 	struct usb_gadget		gadget;
 	struct usb_gadget_driver	*driver;
@@ -506,7 +506,6 @@ struct m66592 {
 	int interrupt;
 	int isochronous;
 	int num_dma;
-	int bi_bufnum;	/* bulk and isochronous's bufnum */
 };
 
 #define gadget_to_m66592(_gadget) container_of(_gadget, struct m66592, gadget)
@@ -547,13 +546,13 @@ static inline void m66592_read_fifo(struct m66592 *m66592,
 {
 	unsigned long fifoaddr = (unsigned long)m66592->reg + offset;
 
-#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
-	len = (len + 3) / 4;
-	insl(fifoaddr, buf, len);
-#else
-	len = (len + 1) / 2;
-	insw(fifoaddr, buf, len);
-#endif
+	if (m66592->pdata->on_chip) {
+		len = (len + 3) / 4;
+		insl(fifoaddr, buf, len);
+	} else {
+		len = (len + 1) / 2;
+		insw(fifoaddr, buf, len);
+	}
 }
 
 static inline void m66592_write(struct m66592 *m66592, u16 val,
@@ -567,33 +566,34 @@ static inline void m66592_write_fifo(struct m66592 *m66592,
 		void *buf, unsigned long len)
 {
 	unsigned long fifoaddr = (unsigned long)m66592->reg + offset;
-#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
-	unsigned long count;
-	unsigned char *pb;
-	int i;
 
-	count = len / 4;
-	outsl(fifoaddr, buf, count);
+	if (m66592->pdata->on_chip) {
+		unsigned long count;
+		unsigned char *pb;
+		int i;
 
-	if (len & 0x00000003) {
-		pb = buf + count * 4;
-		for (i = 0; i < (len & 0x00000003); i++) {
-			if (m66592_read(m66592, M66592_CFBCFG))	/* little */
-				outb(pb[i], fifoaddr + (3 - i));
-			else
-				outb(pb[i], fifoaddr + i);
+		count = len / 4;
+		outsl(fifoaddr, buf, count);
+
+		if (len & 0x00000003) {
+			pb = buf + count * 4;
+			for (i = 0; i < (len & 0x00000003); i++) {
+				if (m66592_read(m66592, M66592_CFBCFG))	/* le */
+					outb(pb[i], fifoaddr + (3 - i));
+				else
+					outb(pb[i], fifoaddr + i);
+			}
+		}
+	} else {
+		unsigned long odd = len & 0x0001;
+
+		len = len / 2;
+		outsw(fifoaddr, buf, len);
+		if (odd) {
+			unsigned char *p = buf + len*2;
+			outb(*p, fifoaddr);
 		}
 	}
-#else
-	unsigned long odd = len & 0x0001;
-
-	len = len / 2;
-	outsw(fifoaddr, buf, len);
-	if (odd) {
-		unsigned char *p = buf + len*2;
-		outb(*p, fifoaddr);
-	}
-#endif	/* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */
 }
 
 static inline void m66592_mdfy(struct m66592 *m66592, u16 val, u16 pat,
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 1a920c70b5a1..f21ca7d27a43 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -336,13 +336,6 @@ config USB_R8A66597_HCD
 	  To compile this driver as a module, choose M here: the
 	  module will be called r8a66597-hcd.
 
-config SUPERH_ON_CHIP_R8A66597
-	boolean "Enable SuperH on-chip R8A66597 USB"
-	depends on USB_R8A66597_HCD && (CPU_SUBTYPE_SH7366 || CPU_SUBTYPE_SH7723 || CPU_SUBTYPE_SH7724)
-	help
-	   This driver enables support for the on-chip R8A66597 in the
-	   SH7366, SH7723 and SH7724 processors.
-
 config USB_WHCI_HCD
 	tristate "Wireless USB Host Controller Interface (WHCI) driver (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
index e18f74946e68..749b53742828 100644
--- a/drivers/usb/host/r8a66597-hcd.c
+++ b/drivers/usb/host/r8a66597-hcd.c
@@ -91,43 +91,43 @@ static int r8a66597_clock_enable(struct r8a66597 *r8a66597)
 	u16 tmp;
 	int i = 0;
 
-#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
-#if defined(CONFIG_HAVE_CLK)
-	clk_enable(r8a66597->clk);
+	if (r8a66597->pdata->on_chip) {
+#ifdef CONFIG_HAVE_CLK
+		clk_enable(r8a66597->clk);
 #endif
-	do {
-		r8a66597_write(r8a66597, SCKE, SYSCFG0);
-		tmp = r8a66597_read(r8a66597, SYSCFG0);
-		if (i++ > 1000) {
-			printk(KERN_ERR "r8a66597: register access fail.\n");
-			return -ENXIO;
-		}
-	} while ((tmp & SCKE) != SCKE);
-	r8a66597_write(r8a66597, 0x04, 0x02);
-#else
-	do {
-		r8a66597_write(r8a66597, USBE, SYSCFG0);
-		tmp = r8a66597_read(r8a66597, SYSCFG0);
-		if (i++ > 1000) {
-			printk(KERN_ERR "r8a66597: register access fail.\n");
-			return -ENXIO;
-		}
-	} while ((tmp & USBE) != USBE);
-	r8a66597_bclr(r8a66597, USBE, SYSCFG0);
-	r8a66597_mdfy(r8a66597, get_xtal_from_pdata(r8a66597->pdata), XTAL,
-			SYSCFG0);
+		do {
+			r8a66597_write(r8a66597, SCKE, SYSCFG0);
+			tmp = r8a66597_read(r8a66597, SYSCFG0);
+			if (i++ > 1000) {
+				printk(KERN_ERR "r8a66597: reg access fail.\n");
+				return -ENXIO;
+			}
+		} while ((tmp & SCKE) != SCKE);
+		r8a66597_write(r8a66597, 0x04, 0x02);
+	} else {
+		do {
+			r8a66597_write(r8a66597, USBE, SYSCFG0);
+			tmp = r8a66597_read(r8a66597, SYSCFG0);
+			if (i++ > 1000) {
+				printk(KERN_ERR "r8a66597: reg access fail.\n");
+				return -ENXIO;
+			}
+		} while ((tmp & USBE) != USBE);
+		r8a66597_bclr(r8a66597, USBE, SYSCFG0);
+		r8a66597_mdfy(r8a66597, get_xtal_from_pdata(r8a66597->pdata),
+			      XTAL, SYSCFG0);
 
-	i = 0;
-	r8a66597_bset(r8a66597, XCKE, SYSCFG0);
-	do {
-		msleep(1);
-		tmp = r8a66597_read(r8a66597, SYSCFG0);
-		if (i++ > 500) {
-			printk(KERN_ERR "r8a66597: register access fail.\n");
-			return -ENXIO;
-		}
-	} while ((tmp & SCKE) != SCKE);
-#endif	/* #if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) */
+		i = 0;
+		r8a66597_bset(r8a66597, XCKE, SYSCFG0);
+		do {
+			msleep(1);
+			tmp = r8a66597_read(r8a66597, SYSCFG0);
+			if (i++ > 500) {
+				printk(KERN_ERR "r8a66597: reg access fail.\n");
+				return -ENXIO;
+			}
+		} while ((tmp & SCKE) != SCKE);
+	}
 
 	return 0;
 }
@@ -136,15 +136,16 @@ static void r8a66597_clock_disable(struct r8a66597 *r8a66597)
 {
 	r8a66597_bclr(r8a66597, SCKE, SYSCFG0);
 	udelay(1);
-#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
-#if defined(CONFIG_HAVE_CLK)
-	clk_disable(r8a66597->clk);
-#endif
-#else
-	r8a66597_bclr(r8a66597, PLLC, SYSCFG0);
-	r8a66597_bclr(r8a66597, XCKE, SYSCFG0);
-	r8a66597_bclr(r8a66597, USBE, SYSCFG0);
+
+	if (r8a66597->pdata->on_chip) {
+#ifdef CONFIG_HAVE_CLK
+		clk_disable(r8a66597->clk);
 #endif
+	} else {
+		r8a66597_bclr(r8a66597, PLLC, SYSCFG0);
+		r8a66597_bclr(r8a66597, XCKE, SYSCFG0);
+		r8a66597_bclr(r8a66597, USBE, SYSCFG0);
+	}
 }
 
 static void r8a66597_enable_port(struct r8a66597 *r8a66597, int port)
@@ -205,7 +206,7 @@ static int enable_controller(struct r8a66597 *r8a66597)
 
 	r8a66597_bset(r8a66597, SIGNE | SACKE, INTENB1);
 
-	for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++)
+	for (port = 0; port < r8a66597->max_root_hub; port++)
 		r8a66597_enable_port(r8a66597, port);
 
 	return 0;
@@ -218,7 +219,7 @@ static void disable_controller(struct r8a66597 *r8a66597)
 	r8a66597_write(r8a66597, 0, INTENB0);
 	r8a66597_write(r8a66597, 0, INTSTS0);
 
-	for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++)
+	for (port = 0; port < r8a66597->max_root_hub; port++)
 		r8a66597_disable_port(r8a66597, port);
 
 	r8a66597_clock_disable(r8a66597);
@@ -249,11 +250,12 @@ static int is_hub_limit(char *devpath)
 	return ((strlen(devpath) >= 4) ? 1 : 0);
 }
 
-static void get_port_number(char *devpath, u16 *root_port, u16 *hub_port)
+static void get_port_number(struct r8a66597 *r8a66597,
+			    char *devpath, u16 *root_port, u16 *hub_port)
 {
 	if (root_port) {
 		*root_port = (devpath[0] & 0x0F) - 1;
-		if (*root_port >= R8A66597_MAX_ROOT_HUB)
+		if (*root_port >= r8a66597->max_root_hub)
 			printk(KERN_ERR "r8a66597: Illegal root port number.\n");
 	}
 	if (hub_port)
@@ -355,7 +357,8 @@ static int make_r8a66597_device(struct r8a66597 *r8a66597,
 	INIT_LIST_HEAD(&dev->device_list);
 	list_add_tail(&dev->device_list, &r8a66597->child_device);
 
-	get_port_number(urb->dev->devpath, &dev->root_port, &dev->hub_port);
+	get_port_number(r8a66597, urb->dev->devpath,
+			&dev->root_port, &dev->hub_port);
 	if (!is_child_device(urb->dev->devpath))
 		r8a66597->root_hub[dev->root_port].dev = dev;
 
@@ -420,7 +423,7 @@ static void free_usb_address(struct r8a66597 *r8a66597,
 	list_del(&dev->device_list);
 	kfree(dev);
 
-	for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) {
+	for (port = 0; port < r8a66597->max_root_hub; port++) {
 		if (r8a66597->root_hub[port].dev == dev) {
 			r8a66597->root_hub[port].dev = NULL;
 			break;
@@ -495,10 +498,20 @@ static void r8a66597_pipe_toggle(struct r8a66597 *r8a66597,
 		r8a66597_bset(r8a66597, SQCLR, pipe->pipectr);
 }
 
+static inline unsigned short mbw_value(struct r8a66597 *r8a66597)
+{
+	if (r8a66597->pdata->on_chip)
+		return MBW_32;
+	else
+		return MBW_16;
+}
+
 /* this function must be called with interrupt disabled */
 static inline void cfifo_change(struct r8a66597 *r8a66597, u16 pipenum)
 {
-	r8a66597_mdfy(r8a66597, MBW | pipenum, MBW | CURPIPE, CFIFOSEL);
+	unsigned short mbw = mbw_value(r8a66597);
+
+	r8a66597_mdfy(r8a66597, mbw | pipenum, mbw | CURPIPE, CFIFOSEL);
 	r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, pipenum);
 }
 
@@ -506,11 +519,13 @@ static inline void cfifo_change(struct r8a66597 *r8a66597, u16 pipenum)
 static inline void fifo_change_from_pipe(struct r8a66597 *r8a66597,
 					 struct r8a66597_pipe *pipe)
 {
-	cfifo_change(r8a66597, 0);
-	r8a66597_mdfy(r8a66597, MBW | 0, MBW | CURPIPE, D0FIFOSEL);
-	r8a66597_mdfy(r8a66597, MBW | 0, MBW | CURPIPE, D1FIFOSEL);
+	unsigned short mbw = mbw_value(r8a66597);
 
-	r8a66597_mdfy(r8a66597, MBW | pipe->info.pipenum, MBW | CURPIPE,
+	cfifo_change(r8a66597, 0);
+	r8a66597_mdfy(r8a66597, mbw | 0, mbw | CURPIPE, D0FIFOSEL);
+	r8a66597_mdfy(r8a66597, mbw | 0, mbw | CURPIPE, D1FIFOSEL);
+
+	r8a66597_mdfy(r8a66597, mbw | pipe->info.pipenum, mbw | CURPIPE,
 		      pipe->fifosel);
 	r8a66597_reg_wait(r8a66597, pipe->fifosel, CURPIPE, pipe->info.pipenum);
 }
@@ -742,9 +757,13 @@ static void enable_r8a66597_pipe_dma(struct r8a66597 *r8a66597,
 				     struct r8a66597_pipe *pipe,
 				     struct urb *urb)
 {
-#if !defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
 	int i;
 	struct r8a66597_pipe_info *info = &pipe->info;
+	unsigned short mbw = mbw_value(r8a66597);
+
+	/* pipe dma is only for external controlles */
+	if (r8a66597->pdata->on_chip)
+		return;
 
 	if ((pipe->info.pipenum != 0) && (info->type != R8A66597_INT)) {
 		for (i = 0; i < R8A66597_MAX_DMA_CHANNEL; i++) {
@@ -763,8 +782,8 @@ static void enable_r8a66597_pipe_dma(struct r8a66597 *r8a66597,
 			set_pipe_reg_addr(pipe, i);
 
 			cfifo_change(r8a66597, 0);
-			r8a66597_mdfy(r8a66597, MBW | pipe->info.pipenum,
-				      MBW | CURPIPE, pipe->fifosel);
+			r8a66597_mdfy(r8a66597, mbw | pipe->info.pipenum,
+				      mbw | CURPIPE, pipe->fifosel);
 
 			r8a66597_reg_wait(r8a66597, pipe->fifosel, CURPIPE,
 					  pipe->info.pipenum);
@@ -772,7 +791,6 @@ static void enable_r8a66597_pipe_dma(struct r8a66597 *r8a66597,
 			break;
 		}
 	}
-#endif	/* #if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) */
 }
 
 /* this function must be called with interrupt disabled */
@@ -1769,7 +1787,7 @@ static void r8a66597_timer(unsigned long _r8a66597)
 
 	spin_lock_irqsave(&r8a66597->lock, flags);
 
-	for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++)
+	for (port = 0; port < r8a66597->max_root_hub; port++)
 		r8a66597_root_hub_control(r8a66597, port);
 
 	spin_unlock_irqrestore(&r8a66597->lock, flags);
@@ -1807,7 +1825,7 @@ static void set_address_zero(struct r8a66597 *r8a66597, struct urb *urb)
 	u16 root_port, hub_port;
 
 	if (usb_address == 0) {
-		get_port_number(urb->dev->devpath,
+		get_port_number(r8a66597, urb->dev->devpath,
 				&root_port, &hub_port);
 		set_devadd_reg(r8a66597, 0,
 			       get_r8a66597_usb_speed(urb->dev->speed),
@@ -2082,7 +2100,7 @@ static int r8a66597_hub_status_data(struct usb_hcd *hcd, char *buf)
 
 	*buf = 0;	/* initialize (no change) */
 
-	for (i = 0; i < R8A66597_MAX_ROOT_HUB; i++) {
+	for (i = 0; i < r8a66597->max_root_hub; i++) {
 		if (r8a66597->root_hub[i].port & 0xffff0000)
 			*buf |= 1 << (i + 1);
 	}
@@ -2097,11 +2115,11 @@ static void r8a66597_hub_descriptor(struct r8a66597 *r8a66597,
 {
 	desc->bDescriptorType = 0x29;
 	desc->bHubContrCurrent = 0;
-	desc->bNbrPorts = R8A66597_MAX_ROOT_HUB;
+	desc->bNbrPorts = r8a66597->max_root_hub;
 	desc->bDescLength = 9;
 	desc->bPwrOn2PwrGood = 0;
 	desc->wHubCharacteristics = cpu_to_le16(0x0011);
-	desc->bitmap[0] = ((1 << R8A66597_MAX_ROOT_HUB) - 1) << 1;
+	desc->bitmap[0] = ((1 << r8a66597->max_root_hub) - 1) << 1;
 	desc->bitmap[1] = ~0;
 }
 
@@ -2129,7 +2147,7 @@ static int r8a66597_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 		}
 		break;
 	case ClearPortFeature:
-		if (wIndex > R8A66597_MAX_ROOT_HUB)
+		if (wIndex > r8a66597->max_root_hub)
 			goto error;
 		if (wLength != 0)
 			goto error;
@@ -2162,12 +2180,12 @@ static int r8a66597_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 		*buf = 0x00;
 		break;
 	case GetPortStatus:
-		if (wIndex > R8A66597_MAX_ROOT_HUB)
+		if (wIndex > r8a66597->max_root_hub)
 			goto error;
 		*(__le32 *)buf = cpu_to_le32(rh->port);
 		break;
 	case SetPortFeature:
-		if (wIndex > R8A66597_MAX_ROOT_HUB)
+		if (wIndex > r8a66597->max_root_hub)
 			goto error;
 		if (wLength != 0)
 			goto error;
@@ -2216,7 +2234,7 @@ static int r8a66597_bus_suspend(struct usb_hcd *hcd)
 
 	dbg("%s", __func__);
 
-	for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) {
+	for (port = 0; port < r8a66597->max_root_hub; port++) {
 		struct r8a66597_root_hub *rh = &r8a66597->root_hub[port];
 		unsigned long dvstctr_reg = get_dvstctr_reg(port);
 
@@ -2247,7 +2265,7 @@ static int r8a66597_bus_resume(struct usb_hcd *hcd)
 
 	dbg("%s", __func__);
 
-	for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) {
+	for (port = 0; port < r8a66597->max_root_hub; port++) {
 		struct r8a66597_root_hub *rh = &r8a66597->root_hub[port];
 		unsigned long dvstctr_reg = get_dvstctr_reg(port);
 
@@ -2305,16 +2323,16 @@ static struct hc_driver r8a66597_hc_driver = {
 };
 
 #if defined(CONFIG_PM)
-static int r8a66597_suspend(struct platform_device *pdev, pm_message_t state)
+static int r8a66597_suspend(struct device *dev)
 {
-	struct r8a66597		*r8a66597 = dev_get_drvdata(&pdev->dev);
+	struct r8a66597		*r8a66597 = dev_get_drvdata(dev);
 	int port;
 
 	dbg("%s", __func__);
 
 	disable_controller(r8a66597);
 
-	for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) {
+	for (port = 0; port < r8a66597->max_root_hub; port++) {
 		struct r8a66597_root_hub *rh = &r8a66597->root_hub[port];
 
 		rh->port = 0x00000000;
@@ -2323,9 +2341,9 @@ static int r8a66597_suspend(struct platform_device *pdev, pm_message_t state)
 	return 0;
 }
 
-static int r8a66597_resume(struct platform_device *pdev)
+static int r8a66597_resume(struct device *dev)
 {
-	struct r8a66597		*r8a66597 = dev_get_drvdata(&pdev->dev);
+	struct r8a66597		*r8a66597 = dev_get_drvdata(dev);
 	struct usb_hcd		*hcd = r8a66597_to_hcd(r8a66597);
 
 	dbg("%s", __func__);
@@ -2335,9 +2353,17 @@ static int r8a66597_resume(struct platform_device *pdev)
 
 	return 0;
 }
+
+static struct dev_pm_ops r8a66597_dev_pm_ops = {
+	.suspend = r8a66597_suspend,
+	.resume = r8a66597_resume,
+	.poweroff = r8a66597_suspend,
+	.restore = r8a66597_resume,
+};
+
+#define R8A66597_DEV_PM_OPS	(&r8a66597_dev_pm_ops)
 #else	/* if defined(CONFIG_PM) */
-#define r8a66597_suspend	NULL
-#define r8a66597_resume		NULL
+#define R8A66597_DEV_PM_OPS	NULL
 #endif
 
 static int __init_or_module r8a66597_remove(struct platform_device *pdev)
@@ -2348,8 +2374,9 @@ static int __init_or_module r8a66597_remove(struct platform_device *pdev)
 	del_timer_sync(&r8a66597->rh_timer);
 	usb_remove_hcd(hcd);
 	iounmap((void *)r8a66597->reg);
-#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) && defined(CONFIG_HAVE_CLK)
-	clk_put(r8a66597->clk);
+#ifdef CONFIG_HAVE_CLK
+	if (r8a66597->pdata->on_chip)
+		clk_put(r8a66597->clk);
 #endif
 	usb_put_hcd(hcd);
 	return 0;
@@ -2357,7 +2384,7 @@ static int __init_or_module r8a66597_remove(struct platform_device *pdev)
 
 static int __devinit r8a66597_probe(struct platform_device *pdev)
 {
-#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) && defined(CONFIG_HAVE_CLK)
+#ifdef CONFIG_HAVE_CLK
 	char clk_name[8];
 #endif
 	struct resource *res = NULL, *ires;
@@ -2419,15 +2446,20 @@ static int __devinit r8a66597_probe(struct platform_device *pdev)
 	r8a66597->pdata = pdev->dev.platform_data;
 	r8a66597->irq_sense_low = irq_trigger == IRQF_TRIGGER_LOW;
 
-#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) && defined(CONFIG_HAVE_CLK)
-	snprintf(clk_name, sizeof(clk_name), "usb%d", pdev->id);
-	r8a66597->clk = clk_get(&pdev->dev, clk_name);
-	if (IS_ERR(r8a66597->clk)) {
-		dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name);
-		ret = PTR_ERR(r8a66597->clk);
-		goto clean_up2;
-	}
+	if (r8a66597->pdata->on_chip) {
+#ifdef CONFIG_HAVE_CLK
+		snprintf(clk_name, sizeof(clk_name), "usb%d", pdev->id);
+		r8a66597->clk = clk_get(&pdev->dev, clk_name);
+		if (IS_ERR(r8a66597->clk)) {
+			dev_err(&pdev->dev, "cannot get clock \"%s\"\n",
+				clk_name);
+			ret = PTR_ERR(r8a66597->clk);
+			goto clean_up2;
+		}
 #endif
+		r8a66597->max_root_hub = 1;
+	} else
+		r8a66597->max_root_hub = 2;
 
 	spin_lock_init(&r8a66597->lock);
 	init_timer(&r8a66597->rh_timer);
@@ -2457,8 +2489,9 @@ static int __devinit r8a66597_probe(struct platform_device *pdev)
 	return 0;
 
 clean_up3:
-#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) && defined(CONFIG_HAVE_CLK)
-	clk_put(r8a66597->clk);
+#ifdef CONFIG_HAVE_CLK
+	if (r8a66597->pdata->on_chip)
+		clk_put(r8a66597->clk);
 clean_up2:
 #endif
 	usb_put_hcd(hcd);
@@ -2473,11 +2506,10 @@ clean_up:
 static struct platform_driver r8a66597_driver = {
 	.probe =	r8a66597_probe,
 	.remove =	r8a66597_remove,
-	.suspend =	r8a66597_suspend,
-	.resume =	r8a66597_resume,
 	.driver		= {
 		.name = (char *) hcd_name,
 		.owner	= THIS_MODULE,
+		.pm	= R8A66597_DEV_PM_OPS,
 	},
 };
 
diff --git a/drivers/usb/host/r8a66597.h b/drivers/usb/host/r8a66597.h
index d72680b433f9..228e3fb23854 100644
--- a/drivers/usb/host/r8a66597.h
+++ b/drivers/usb/host/r8a66597.h
@@ -26,390 +26,16 @@
 #ifndef __R8A66597_H__
 #define __R8A66597_H__
 
-#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) && defined(CONFIG_HAVE_CLK)
+#ifdef CONFIG_HAVE_CLK
 #include <linux/clk.h>
 #endif
 
 #include <linux/usb/r8a66597.h>
 
-#define SYSCFG0		0x00
-#define SYSCFG1		0x02
-#define SYSSTS0		0x04
-#define SYSSTS1		0x06
-#define DVSTCTR0	0x08
-#define DVSTCTR1	0x0A
-#define TESTMODE	0x0C
-#define PINCFG		0x0E
-#define DMA0CFG		0x10
-#define DMA1CFG		0x12
-#define CFIFO		0x14
-#define D0FIFO		0x18
-#define D1FIFO		0x1C
-#define CFIFOSEL	0x20
-#define CFIFOCTR	0x22
-#define CFIFOSIE	0x24
-#define D0FIFOSEL	0x28
-#define D0FIFOCTR	0x2A
-#define D1FIFOSEL	0x2C
-#define D1FIFOCTR	0x2E
-#define INTENB0		0x30
-#define INTENB1		0x32
-#define INTENB2		0x34
-#define BRDYENB		0x36
-#define NRDYENB		0x38
-#define BEMPENB		0x3A
-#define SOFCFG		0x3C
-#define INTSTS0		0x40
-#define INTSTS1		0x42
-#define INTSTS2		0x44
-#define BRDYSTS		0x46
-#define NRDYSTS		0x48
-#define BEMPSTS		0x4A
-#define FRMNUM		0x4C
-#define UFRMNUM		0x4E
-#define USBADDR		0x50
-#define USBREQ		0x54
-#define USBVAL		0x56
-#define USBINDX		0x58
-#define USBLENG		0x5A
-#define DCPCFG		0x5C
-#define DCPMAXP		0x5E
-#define DCPCTR		0x60
-#define PIPESEL		0x64
-#define PIPECFG		0x68
-#define PIPEBUF		0x6A
-#define PIPEMAXP	0x6C
-#define PIPEPERI	0x6E
-#define PIPE1CTR	0x70
-#define PIPE2CTR	0x72
-#define PIPE3CTR	0x74
-#define PIPE4CTR	0x76
-#define PIPE5CTR	0x78
-#define PIPE6CTR	0x7A
-#define PIPE7CTR	0x7C
-#define PIPE8CTR	0x7E
-#define PIPE9CTR	0x80
-#define PIPE1TRE	0x90
-#define PIPE1TRN	0x92
-#define PIPE2TRE	0x94
-#define PIPE2TRN	0x96
-#define PIPE3TRE	0x98
-#define PIPE3TRN	0x9A
-#define PIPE4TRE	0x9C
-#define	PIPE4TRN	0x9E
-#define	PIPE5TRE	0xA0
-#define	PIPE5TRN	0xA2
-#define DEVADD0		0xD0
-#define DEVADD1		0xD2
-#define DEVADD2		0xD4
-#define DEVADD3		0xD6
-#define DEVADD4		0xD8
-#define DEVADD5		0xDA
-#define DEVADD6		0xDC
-#define DEVADD7		0xDE
-#define DEVADD8		0xE0
-#define DEVADD9		0xE2
-#define DEVADDA		0xE4
-
-/* System Configuration Control Register */
-#define	XTAL		0xC000	/* b15-14: Crystal selection */
-#define	  XTAL48	 0x8000	  /* 48MHz */
-#define	  XTAL24	 0x4000	  /* 24MHz */
-#define	  XTAL12	 0x0000	  /* 12MHz */
-#define	XCKE		0x2000	/* b13: External clock enable */
-#define	PLLC		0x0800	/* b11: PLL control */
-#define	SCKE		0x0400	/* b10: USB clock enable */
-#define	PCSDIS		0x0200	/* b9: not CS wakeup */
-#define	LPSME		0x0100	/* b8: Low power sleep mode */
-#define	HSE		0x0080	/* b7: Hi-speed enable */
-#define	DCFM		0x0040	/* b6: Controller function select  */
-#define	DRPD		0x0020	/* b5: D+/- pull down control */
-#define	DPRPU		0x0010	/* b4: D+ pull up control */
-#define	USBE		0x0001	/* b0: USB module operation enable */
-
-/* System Configuration Status Register */
-#define	OVCBIT		0x8000	/* b15-14: Over-current bit */
-#define	OVCMON		0xC000	/* b15-14: Over-current monitor */
-#define	SOFEA		0x0020	/* b5: SOF monitor */
-#define	IDMON		0x0004	/* b3: ID-pin monitor */
-#define	LNST		0x0003	/* b1-0: D+, D- line status */
-#define	  SE1		 0x0003	  /* SE1 */
-#define	  FS_KSTS	 0x0002	  /* Full-Speed K State */
-#define	  FS_JSTS	 0x0001	  /* Full-Speed J State */
-#define	  LS_JSTS	 0x0002	  /* Low-Speed J State */
-#define	  LS_KSTS	 0x0001	  /* Low-Speed K State */
-#define	  SE0		 0x0000	  /* SE0 */
-
-/* Device State Control Register */
-#define	EXTLP0		0x0400	/* b10: External port */
-#define	VBOUT		0x0200	/* b9: VBUS output */
-#define	WKUP		0x0100	/* b8: Remote wakeup */
-#define	RWUPE		0x0080	/* b7: Remote wakeup sense */
-#define	USBRST		0x0040	/* b6: USB reset enable */
-#define	RESUME		0x0020	/* b5: Resume enable */
-#define	UACT		0x0010	/* b4: USB bus enable */
-#define	RHST		0x0007	/* b1-0: Reset handshake status */
-#define	  HSPROC	 0x0004	  /* HS handshake is processing */
-#define	  HSMODE	 0x0003	  /* Hi-Speed mode */
-#define	  FSMODE	 0x0002	  /* Full-Speed mode */
-#define	  LSMODE	 0x0001	  /* Low-Speed mode */
-#define	  UNDECID	 0x0000	  /* Undecided */
-
-/* Test Mode Register */
-#define	UTST			0x000F	/* b3-0: Test select */
-#define	  H_TST_PACKET		 0x000C	  /* HOST TEST Packet */
-#define	  H_TST_SE0_NAK		 0x000B	  /* HOST TEST SE0 NAK */
-#define	  H_TST_K		 0x000A	  /* HOST TEST K */
-#define	  H_TST_J		 0x0009	  /* HOST TEST J */
-#define	  H_TST_NORMAL		 0x0000	  /* HOST Normal Mode */
-#define	  P_TST_PACKET		 0x0004	  /* PERI TEST Packet */
-#define	  P_TST_SE0_NAK		 0x0003	  /* PERI TEST SE0 NAK */
-#define	  P_TST_K		 0x0002	  /* PERI TEST K */
-#define	  P_TST_J		 0x0001	  /* PERI TEST J */
-#define	  P_TST_NORMAL		 0x0000	  /* PERI Normal Mode */
-
-/* Data Pin Configuration Register */
-#define	LDRV			0x8000	/* b15: Drive Current Adjust */
-#define	  VIF1			  0x0000		/* VIF = 1.8V */
-#define	  VIF3			  0x8000		/* VIF = 3.3V */
-#define	INTA			0x0001	/* b1: USB INT-pin active */
-
-/* DMAx Pin Configuration Register */
-#define	DREQA			0x4000	/* b14: Dreq active select */
-#define	BURST			0x2000	/* b13: Burst mode */
-#define	DACKA			0x0400	/* b10: Dack active select */
-#define	DFORM			0x0380	/* b9-7: DMA mode select */
-#define	  CPU_ADR_RD_WR		 0x0000	  /* Address + RD/WR mode (CPU bus) */
-#define	  CPU_DACK_RD_WR	 0x0100	  /* DACK + RD/WR mode (CPU bus) */
-#define	  CPU_DACK_ONLY		 0x0180	  /* DACK only mode (CPU bus) */
-#define	  SPLIT_DACK_ONLY	 0x0200	  /* DACK only mode (SPLIT bus) */
-#define	DENDA			0x0040	/* b6: Dend active select */
-#define	PKTM			0x0020	/* b5: Packet mode */
-#define	DENDE			0x0010	/* b4: Dend enable */
-#define	OBUS			0x0004	/* b2: OUTbus mode */
-
-/* CFIFO/DxFIFO Port Select Register */
-#define	RCNT		0x8000	/* b15: Read count mode */
-#define	REW		0x4000	/* b14: Buffer rewind */
-#define	DCLRM		0x2000	/* b13: DMA buffer clear mode */
-#define	DREQE		0x1000	/* b12: DREQ output enable */
-#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
-#define	MBW		0x0800
-#else
-#define	MBW		0x0400	/* b10: Maximum bit width for FIFO access */
-#endif
-#define	  MBW_8		 0x0000	  /*  8bit */
-#define	  MBW_16	 0x0400	  /* 16bit */
-#define	BIGEND		0x0100	/* b8: Big endian mode */
-#define	  BYTE_LITTLE	 0x0000		/* little dendian */
-#define	  BYTE_BIG	 0x0100		/* big endifan */
-#define	ISEL		0x0020	/* b5: DCP FIFO port direction select */
-#define	CURPIPE		0x000F	/* b2-0: PIPE select */
-
-/* CFIFO/DxFIFO Port Control Register */
-#define	BVAL		0x8000	/* b15: Buffer valid flag */
-#define	BCLR		0x4000	/* b14: Buffer clear */
-#define	FRDY		0x2000	/* b13: FIFO ready */
-#define	DTLN		0x0FFF	/* b11-0: FIFO received data length */
-
-/* Interrupt Enable Register 0 */
-#define	VBSE	0x8000	/* b15: VBUS interrupt */
-#define	RSME	0x4000	/* b14: Resume interrupt */
-#define	SOFE	0x2000	/* b13: Frame update interrupt */
-#define	DVSE	0x1000	/* b12: Device state transition interrupt */
-#define	CTRE	0x0800	/* b11: Control transfer stage transition interrupt */
-#define	BEMPE	0x0400	/* b10: Buffer empty interrupt */
-#define	NRDYE	0x0200	/* b9: Buffer not ready interrupt */
-#define	BRDYE	0x0100	/* b8: Buffer ready interrupt */
-
-/* Interrupt Enable Register 1 */
-#define	OVRCRE		0x8000	/* b15: Over-current interrupt */
-#define	BCHGE		0x4000	/* b14: USB us chenge interrupt */
-#define	DTCHE		0x1000	/* b12: Detach sense interrupt */
-#define	ATTCHE		0x0800	/* b11: Attach sense interrupt */
-#define	EOFERRE		0x0040	/* b6: EOF error interrupt */
-#define	SIGNE		0x0020	/* b5: SETUP IGNORE interrupt */
-#define	SACKE		0x0010	/* b4: SETUP ACK interrupt */
-
-/* BRDY Interrupt Enable/Status Register */
-#define	BRDY9		0x0200	/* b9: PIPE9 */
-#define	BRDY8		0x0100	/* b8: PIPE8 */
-#define	BRDY7		0x0080	/* b7: PIPE7 */
-#define	BRDY6		0x0040	/* b6: PIPE6 */
-#define	BRDY5		0x0020	/* b5: PIPE5 */
-#define	BRDY4		0x0010	/* b4: PIPE4 */
-#define	BRDY3		0x0008	/* b3: PIPE3 */
-#define	BRDY2		0x0004	/* b2: PIPE2 */
-#define	BRDY1		0x0002	/* b1: PIPE1 */
-#define	BRDY0		0x0001	/* b1: PIPE0 */
-
-/* NRDY Interrupt Enable/Status Register */
-#define	NRDY9		0x0200	/* b9: PIPE9 */
-#define	NRDY8		0x0100	/* b8: PIPE8 */
-#define	NRDY7		0x0080	/* b7: PIPE7 */
-#define	NRDY6		0x0040	/* b6: PIPE6 */
-#define	NRDY5		0x0020	/* b5: PIPE5 */
-#define	NRDY4		0x0010	/* b4: PIPE4 */
-#define	NRDY3		0x0008	/* b3: PIPE3 */
-#define	NRDY2		0x0004	/* b2: PIPE2 */
-#define	NRDY1		0x0002	/* b1: PIPE1 */
-#define	NRDY0		0x0001	/* b1: PIPE0 */
-
-/* BEMP Interrupt Enable/Status Register */
-#define	BEMP9		0x0200	/* b9: PIPE9 */
-#define	BEMP8		0x0100	/* b8: PIPE8 */
-#define	BEMP7		0x0080	/* b7: PIPE7 */
-#define	BEMP6		0x0040	/* b6: PIPE6 */
-#define	BEMP5		0x0020	/* b5: PIPE5 */
-#define	BEMP4		0x0010	/* b4: PIPE4 */
-#define	BEMP3		0x0008	/* b3: PIPE3 */
-#define	BEMP2		0x0004	/* b2: PIPE2 */
-#define	BEMP1		0x0002	/* b1: PIPE1 */
-#define	BEMP0		0x0001	/* b0: PIPE0 */
-
-/* SOF Pin Configuration Register */
-#define	TRNENSEL	0x0100	/* b8: Select transaction enable period */
-#define	BRDYM		0x0040	/* b6: BRDY clear timing */
-#define	INTL		0x0020	/* b5: Interrupt sense select */
-#define	EDGESTS		0x0010	/* b4:  */
-#define	SOFMODE		0x000C	/* b3-2: SOF pin select */
-#define	  SOF_125US	 0x0008	  /* SOF OUT 125us Frame Signal */
-#define	  SOF_1MS	 0x0004	  /* SOF OUT 1ms Frame Signal */
-#define	  SOF_DISABLE	 0x0000	  /* SOF OUT Disable */
-
-/* Interrupt Status Register 0 */
-#define	VBINT	0x8000	/* b15: VBUS interrupt */
-#define	RESM	0x4000	/* b14: Resume interrupt */
-#define	SOFR	0x2000	/* b13: SOF frame update interrupt */
-#define	DVST	0x1000	/* b12: Device state transition interrupt */
-#define	CTRT	0x0800	/* b11: Control transfer stage transition interrupt */
-#define	BEMP	0x0400	/* b10: Buffer empty interrupt */
-#define	NRDY	0x0200	/* b9: Buffer not ready interrupt */
-#define	BRDY	0x0100	/* b8: Buffer ready interrupt */
-#define	VBSTS	0x0080	/* b7: VBUS input port */
-#define	DVSQ	0x0070	/* b6-4: Device state */
-#define	  DS_SPD_CNFG	 0x0070	  /* Suspend Configured */
-#define	  DS_SPD_ADDR	 0x0060	  /* Suspend Address */
-#define	  DS_SPD_DFLT	 0x0050	  /* Suspend Default */
-#define	  DS_SPD_POWR	 0x0040	  /* Suspend Powered */
-#define	  DS_SUSP	 0x0040	  /* Suspend */
-#define	  DS_CNFG	 0x0030	  /* Configured */
-#define	  DS_ADDS	 0x0020	  /* Address */
-#define	  DS_DFLT	 0x0010	  /* Default */
-#define	  DS_POWR	 0x0000	  /* Powered */
-#define	DVSQS		0x0030	/* b5-4: Device state */
-#define	VALID		0x0008	/* b3: Setup packet detected flag */
-#define	CTSQ		0x0007	/* b2-0: Control transfer stage */
-#define	  CS_SQER	 0x0006	  /* Sequence error */
-#define	  CS_WRND	 0x0005	  /* Control write nodata status stage */
-#define	  CS_WRSS	 0x0004	  /* Control write status stage */
-#define	  CS_WRDS	 0x0003	  /* Control write data stage */
-#define	  CS_RDSS	 0x0002	  /* Control read status stage */
-#define	  CS_RDDS	 0x0001	  /* Control read data stage */
-#define	  CS_IDST	 0x0000	  /* Idle or setup stage */
-
-/* Interrupt Status Register 1 */
-#define	OVRCR		0x8000	/* b15: Over-current interrupt */
-#define	BCHG		0x4000	/* b14: USB bus chenge interrupt */
-#define	DTCH		0x1000	/* b12: Detach sense interrupt */
-#define	ATTCH		0x0800	/* b11: Attach sense interrupt */
-#define	EOFERR		0x0040	/* b6: EOF-error interrupt */
-#define	SIGN		0x0020	/* b5: Setup ignore interrupt */
-#define	SACK		0x0010	/* b4: Setup acknowledge interrupt */
-
-/* Frame Number Register */
-#define	OVRN		0x8000	/* b15: Overrun error */
-#define	CRCE		0x4000	/* b14: Received data error */
-#define	FRNM		0x07FF	/* b10-0: Frame number */
-
-/* Micro Frame Number Register */
-#define	UFRNM		0x0007	/* b2-0: Micro frame number */
-
-/* Default Control Pipe Maxpacket Size Register */
-/* Pipe Maxpacket Size Register */
-#define	DEVSEL	0xF000	/* b15-14: Device address select */
-#define	MAXP	0x007F	/* b6-0: Maxpacket size of default control pipe */
-
-/* Default Control Pipe Control Register */
-#define	BSTS		0x8000	/* b15: Buffer status */
-#define	SUREQ		0x4000	/* b14: Send USB request  */
-#define	CSCLR		0x2000	/* b13: complete-split status clear */
-#define	CSSTS		0x1000	/* b12: complete-split status */
-#define	SUREQCLR	0x0800	/* b11: stop setup request */
-#define	SQCLR		0x0100	/* b8: Sequence toggle bit clear */
-#define	SQSET		0x0080	/* b7: Sequence toggle bit set */
-#define	SQMON		0x0040	/* b6: Sequence toggle bit monitor */
-#define	PBUSY		0x0020	/* b5: pipe busy */
-#define	PINGE		0x0010	/* b4: ping enable */
-#define	CCPL		0x0004	/* b2: Enable control transfer complete */
-#define	PID		0x0003	/* b1-0: Response PID */
-#define	  PID_STALL11	 0x0003	  /* STALL */
-#define	  PID_STALL	 0x0002	  /* STALL */
-#define	  PID_BUF	 0x0001	  /* BUF */
-#define	  PID_NAK	 0x0000	  /* NAK */
-
-/* Pipe Window Select Register */
-#define	PIPENM		0x0007	/* b2-0: Pipe select */
-
-/* Pipe Configuration Register */
-#define	R8A66597_TYP	0xC000	/* b15-14: Transfer type */
-#define	  R8A66597_ISO	 0xC000		  /* Isochronous */
-#define	  R8A66597_INT	 0x8000		  /* Interrupt */
-#define	  R8A66597_BULK	 0x4000		  /* Bulk */
-#define	R8A66597_BFRE	0x0400	/* b10: Buffer ready interrupt mode select */
-#define	R8A66597_DBLB	0x0200	/* b9: Double buffer mode select */
-#define	R8A66597_CNTMD	0x0100	/* b8: Continuous transfer mode select */
-#define	R8A66597_SHTNAK	0x0080	/* b7: Transfer end NAK */
-#define	R8A66597_DIR	0x0010	/* b4: Transfer direction select */
-#define	R8A66597_EPNUM	0x000F	/* b3-0: Eendpoint number select */
-
-/* Pipe Buffer Configuration Register */
-#define	BUFSIZE		0x7C00	/* b14-10: Pipe buffer size */
-#define	BUFNMB		0x007F	/* b6-0: Pipe buffer number */
-#define	PIPE0BUF	256
-#define	PIPExBUF	64
-
-/* Pipe Maxpacket Size Register */
-#define	MXPS		0x07FF	/* b10-0: Maxpacket size */
-
-/* Pipe Cycle Configuration Register */
-#define	IFIS	0x1000	/* b12: Isochronous in-buffer flush mode select */
-#define	IITV	0x0007	/* b2-0: Isochronous interval */
-
-/* Pipex Control Register */
-#define	BSTS	0x8000	/* b15: Buffer status */
-#define	INBUFM	0x4000	/* b14: IN buffer monitor (Only for PIPE1 to 5) */
-#define	CSCLR	0x2000	/* b13: complete-split status clear */
-#define	CSSTS	0x1000	/* b12: complete-split status */
-#define	ATREPM	0x0400	/* b10: Auto repeat mode */
-#define	ACLRM	0x0200	/* b9: Out buffer auto clear mode */
-#define	SQCLR	0x0100	/* b8: Sequence toggle bit clear */
-#define	SQSET	0x0080	/* b7: Sequence toggle bit set */
-#define	SQMON	0x0040	/* b6: Sequence toggle bit monitor */
-#define	PBUSY	0x0020	/* b5: pipe busy */
-#define	PID	0x0003	/* b1-0: Response PID */
-
-/* PIPExTRE */
-#define	TRENB		0x0200	/* b9: Transaction counter enable */
-#define	TRCLR		0x0100	/* b8: Transaction counter clear */
-
-/* PIPExTRN */
-#define	TRNCNT		0xFFFF	/* b15-0: Transaction counter */
-
-/* DEVADDx */
-#define	UPPHUB		0x7800
-#define	HUBPORT		0x0700
-#define	USBSPD		0x00C0
-#define	RTPORT		0x0001
-
 #define R8A66597_MAX_NUM_PIPE		10
 #define R8A66597_BUF_BSIZE		8
 #define R8A66597_MAX_DEVICE		10
-#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
-#define R8A66597_MAX_ROOT_HUB		1
-#else
 #define R8A66597_MAX_ROOT_HUB		2
-#endif
 #define R8A66597_MAX_SAMPLING		5
 #define R8A66597_RH_POLL_TIME		10
 #define R8A66597_MAX_DMA_CHANNEL	2
@@ -487,7 +113,7 @@ struct r8a66597_root_hub {
 struct r8a66597 {
 	spinlock_t lock;
 	unsigned long reg;
-#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) && defined(CONFIG_HAVE_CLK)
+#ifdef CONFIG_HAVE_CLK
 	struct clk *clk;
 #endif
 	struct r8a66597_platdata	*pdata;
@@ -504,6 +130,7 @@ struct r8a66597 {
 	unsigned short interval_map;
 	unsigned char pipe_cnt[R8A66597_MAX_NUM_PIPE];
 	unsigned char dma_map;
+	unsigned int max_root_hub;
 
 	struct list_head child_device;
 	unsigned long child_connect_map[4];
@@ -550,21 +177,22 @@ static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597,
 				      unsigned long offset, u16 *buf,
 				      int len)
 {
-#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
 	unsigned long fifoaddr = r8a66597->reg + offset;
 	unsigned long count;
 
-	count = len / 4;
-	insl(fifoaddr, buf, count);
+	if (r8a66597->pdata->on_chip) {
+		count = len / 4;
+		insl(fifoaddr, buf, count);
 
-	if (len & 0x00000003) {
-		unsigned long tmp = inl(fifoaddr);
-		memcpy((unsigned char *)buf + count * 4, &tmp, len & 0x03);
+		if (len & 0x00000003) {
+			unsigned long tmp = inl(fifoaddr);
+			memcpy((unsigned char *)buf + count * 4, &tmp,
+			       len & 0x03);
+		}
+	} else {
+		len = (len + 1) / 2;
+		insw(fifoaddr, buf, len);
 	}
-#else
-	len = (len + 1) / 2;
-	insw(r8a66597->reg + offset, buf, len);
-#endif
 }
 
 static inline void r8a66597_write(struct r8a66597 *r8a66597, u16 val,
@@ -578,33 +206,33 @@ static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597,
 				       int len)
 {
 	unsigned long fifoaddr = r8a66597->reg + offset;
-#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
 	unsigned long count;
 	unsigned char *pb;
 	int i;
 
-	count = len / 4;
-	outsl(fifoaddr, buf, count);
+	if (r8a66597->pdata->on_chip) {
+		count = len / 4;
+		outsl(fifoaddr, buf, count);
 
-	if (len & 0x00000003) {
-		pb = (unsigned char *)buf + count * 4;
-		for (i = 0; i < (len & 0x00000003); i++) {
-			if (r8a66597_read(r8a66597, CFIFOSEL) & BIGEND)
-				outb(pb[i], fifoaddr + i);
-			else
-				outb(pb[i], fifoaddr + 3 - i);
+		if (len & 0x00000003) {
+			pb = (unsigned char *)buf + count * 4;
+			for (i = 0; i < (len & 0x00000003); i++) {
+				if (r8a66597_read(r8a66597, CFIFOSEL) & BIGEND)
+					outb(pb[i], fifoaddr + i);
+				else
+					outb(pb[i], fifoaddr + 3 - i);
+			}
+		}
+	} else {
+		int odd = len & 0x0001;
+
+		len = len / 2;
+		outsw(fifoaddr, buf, len);
+		if (unlikely(odd)) {
+			buf = &buf[len];
+			outb((unsigned char)*buf, fifoaddr);
 		}
 	}
-#else
-	int odd = len & 0x0001;
-
-	len = len / 2;
-	outsw(fifoaddr, buf, len);
-	if (unlikely(odd)) {
-		buf = &buf[len];
-		outb((unsigned char)*buf, fifoaddr);
-	}
-#endif
 }
 
 static inline void r8a66597_mdfy(struct r8a66597 *r8a66597,
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 3b54b3940178..7e2c9774f08f 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -1867,7 +1867,7 @@ config FB_W100
 
 config FB_SH_MOBILE_LCDC
 	tristate "SuperH Mobile LCDC framebuffer support"
-	depends on FB && SUPERH
+	depends on FB && SUPERH && HAVE_CLK
 	select FB_SYS_FILLRECT
 	select FB_SYS_COPYAREA
 	select FB_SYS_IMAGEBLIT
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index 07f22b625632..fc3f9662ceae 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -42,11 +42,9 @@ struct sh_mobile_lcdc_chan {
 struct sh_mobile_lcdc_priv {
 	void __iomem *base;
 	int irq;
-#ifdef CONFIG_HAVE_CLK
 	atomic_t clk_usecnt;
 	struct clk *dot_clk;
 	struct clk *clk;
-#endif
 	unsigned long lddckr;
 	struct sh_mobile_lcdc_chan ch[2];
 	int started;
@@ -156,6 +154,7 @@ static void lcdc_sys_write_index(void *handle, unsigned long data)
 	lcdc_write(ch->lcdc, _LDDWD0R, data | 0x10000000);
 	lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
 	lcdc_write(ch->lcdc, _LDDWAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0));
+	lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
 }
 
 static void lcdc_sys_write_data(void *handle, unsigned long data)
@@ -165,6 +164,7 @@ static void lcdc_sys_write_data(void *handle, unsigned long data)
 	lcdc_write(ch->lcdc, _LDDWD0R, data | 0x11000000);
 	lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
 	lcdc_write(ch->lcdc, _LDDWAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0));
+	lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
 }
 
 static unsigned long lcdc_sys_read_data(void *handle)
@@ -175,8 +175,9 @@ static unsigned long lcdc_sys_read_data(void *handle)
 	lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
 	lcdc_write(ch->lcdc, _LDDRAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0));
 	udelay(1);
+	lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
 
-	return lcdc_read(ch->lcdc, _LDDRDR) & 0xffff;
+	return lcdc_read(ch->lcdc, _LDDRDR) & 0x3ffff;
 }
 
 struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = {
@@ -185,7 +186,6 @@ struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = {
 	lcdc_sys_read_data,
 };
 
-#ifdef CONFIG_HAVE_CLK
 static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv)
 {
 	if (atomic_inc_and_test(&priv->clk_usecnt)) {
@@ -203,10 +203,6 @@ static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv)
 		clk_disable(priv->clk);
 	}
 }
-#else
-static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv) {}
-static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv) {}
-#endif
 
 static int sh_mobile_lcdc_sginit(struct fb_info *info,
 				  struct list_head *pagelist)
@@ -520,7 +516,6 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
 		board_cfg = &ch->cfg.board_cfg;
 		if (board_cfg->display_off)
 			board_cfg->display_off(board_cfg->board_data);
-
 	}
 
 	/* stop the lcdc */
@@ -579,9 +574,7 @@ static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev,
 				       int clock_source,
 				       struct sh_mobile_lcdc_priv *priv)
 {
-#ifdef CONFIG_HAVE_CLK
 	char clk_name[8];
-#endif
 	char *str;
 	int icksel;
 
@@ -595,7 +588,6 @@ static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev,
 
 	priv->lddckr = icksel << 16;
 
-#ifdef CONFIG_HAVE_CLK
 	atomic_set(&priv->clk_usecnt, -1);
 	snprintf(clk_name, sizeof(clk_name), "lcdc%d", pdev->id);
 	priv->clk = clk_get(&pdev->dev, clk_name);
@@ -603,7 +595,7 @@ static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev,
 		dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name);
 		return PTR_ERR(priv->clk);
 	}
-	
+
 	if (str) {
 		priv->dot_clk = clk_get(&pdev->dev, str);
 		if (IS_ERR(priv->dot_clk)) {
@@ -612,7 +604,6 @@ static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev,
 			return PTR_ERR(priv->dot_clk);
 		}
 	}
-#endif
 
 	return 0;
 }
@@ -947,11 +938,9 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev)
 		framebuffer_release(info);
 	}
 
-#ifdef CONFIG_HAVE_CLK
 	if (priv->dot_clk)
 		clk_put(priv->dot_clk);
 	clk_put(priv->clk);
-#endif
 
 	if (priv->base)
 		iounmap(priv->base);
diff --git a/include/linux/usb/m66592.h b/include/linux/usb/m66592.h
new file mode 100644
index 000000000000..cda9625e7df0
--- /dev/null
+++ b/include/linux/usb/m66592.h
@@ -0,0 +1,44 @@
+/*
+ * M66592 driver platform data
+ *
+ * Copyright (C) 2009  Renesas Solutions Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef __LINUX_USB_M66592_H
+#define __LINUX_USB_M66592_H
+
+#define M66592_PLATDATA_XTAL_12MHZ	0x01
+#define M66592_PLATDATA_XTAL_24MHZ	0x02
+#define M66592_PLATDATA_XTAL_48MHZ	0x03
+
+struct m66592_platdata {
+	/* one = on chip controller, zero = external controller */
+	unsigned	on_chip:1;
+
+	/* one = big endian, zero = little endian */
+	unsigned	endian:1;
+
+	/* (external controller only) M66592_PLATDATA_XTAL_nnMHZ */
+	unsigned	xtal:2;
+
+	/* (external controller only) one = 3.3V, zero = 1.5V */
+	unsigned	vif:1;
+
+};
+
+#endif /* __LINUX_USB_M66592_H */
+
diff --git a/include/linux/usb/r8a66597.h b/include/linux/usb/r8a66597.h
index e9f0384fa20c..26d216734057 100644
--- a/include/linux/usb/r8a66597.h
+++ b/include/linux/usb/r8a66597.h
@@ -28,9 +28,12 @@
 #define R8A66597_PLATDATA_XTAL_48MHZ	0x03
 
 struct r8a66597_platdata {
-	/* This ops can controll port power instead of DVSTCTR register. */
+	/* This callback can control port power instead of DVSTCTR register. */
 	void (*port_power)(int port, int power);
 
+	/* set one = on chip controller, set zero = external controller */
+	unsigned	on_chip:1;
+
 	/* (external controller only) set R8A66597_PLATDATA_XTAL_nnMHZ */
 	unsigned	xtal:2;
 
@@ -40,5 +43,373 @@ struct r8a66597_platdata {
 	/* set one = big endian, set zero = little endian */
 	unsigned	endian:1;
 };
-#endif
+
+/* Register definitions */
+#define SYSCFG0		0x00
+#define SYSCFG1		0x02
+#define SYSSTS0		0x04
+#define SYSSTS1		0x06
+#define DVSTCTR0	0x08
+#define DVSTCTR1	0x0A
+#define TESTMODE	0x0C
+#define PINCFG		0x0E
+#define DMA0CFG		0x10
+#define DMA1CFG		0x12
+#define CFIFO		0x14
+#define D0FIFO		0x18
+#define D1FIFO		0x1C
+#define CFIFOSEL	0x20
+#define CFIFOCTR	0x22
+#define CFIFOSIE	0x24
+#define D0FIFOSEL	0x28
+#define D0FIFOCTR	0x2A
+#define D1FIFOSEL	0x2C
+#define D1FIFOCTR	0x2E
+#define INTENB0		0x30
+#define INTENB1		0x32
+#define INTENB2		0x34
+#define BRDYENB		0x36
+#define NRDYENB		0x38
+#define BEMPENB		0x3A
+#define SOFCFG		0x3C
+#define INTSTS0		0x40
+#define INTSTS1		0x42
+#define INTSTS2		0x44
+#define BRDYSTS		0x46
+#define NRDYSTS		0x48
+#define BEMPSTS		0x4A
+#define FRMNUM		0x4C
+#define UFRMNUM		0x4E
+#define USBADDR		0x50
+#define USBREQ		0x54
+#define USBVAL		0x56
+#define USBINDX		0x58
+#define USBLENG		0x5A
+#define DCPCFG		0x5C
+#define DCPMAXP		0x5E
+#define DCPCTR		0x60
+#define PIPESEL		0x64
+#define PIPECFG		0x68
+#define PIPEBUF		0x6A
+#define PIPEMAXP	0x6C
+#define PIPEPERI	0x6E
+#define PIPE1CTR	0x70
+#define PIPE2CTR	0x72
+#define PIPE3CTR	0x74
+#define PIPE4CTR	0x76
+#define PIPE5CTR	0x78
+#define PIPE6CTR	0x7A
+#define PIPE7CTR	0x7C
+#define PIPE8CTR	0x7E
+#define PIPE9CTR	0x80
+#define PIPE1TRE	0x90
+#define PIPE1TRN	0x92
+#define PIPE2TRE	0x94
+#define PIPE2TRN	0x96
+#define PIPE3TRE	0x98
+#define PIPE3TRN	0x9A
+#define PIPE4TRE	0x9C
+#define	PIPE4TRN	0x9E
+#define	PIPE5TRE	0xA0
+#define	PIPE5TRN	0xA2
+#define DEVADD0		0xD0
+#define DEVADD1		0xD2
+#define DEVADD2		0xD4
+#define DEVADD3		0xD6
+#define DEVADD4		0xD8
+#define DEVADD5		0xDA
+#define DEVADD6		0xDC
+#define DEVADD7		0xDE
+#define DEVADD8		0xE0
+#define DEVADD9		0xE2
+#define DEVADDA		0xE4
+
+/* System Configuration Control Register */
+#define	XTAL		0xC000	/* b15-14: Crystal selection */
+#define	  XTAL48	 0x8000	  /* 48MHz */
+#define	  XTAL24	 0x4000	  /* 24MHz */
+#define	  XTAL12	 0x0000	  /* 12MHz */
+#define	XCKE		0x2000	/* b13: External clock enable */
+#define	PLLC		0x0800	/* b11: PLL control */
+#define	SCKE		0x0400	/* b10: USB clock enable */
+#define	PCSDIS		0x0200	/* b9: not CS wakeup */
+#define	LPSME		0x0100	/* b8: Low power sleep mode */
+#define	HSE		0x0080	/* b7: Hi-speed enable */
+#define	DCFM		0x0040	/* b6: Controller function select  */
+#define	DRPD		0x0020	/* b5: D+/- pull down control */
+#define	DPRPU		0x0010	/* b4: D+ pull up control */
+#define	USBE		0x0001	/* b0: USB module operation enable */
+
+/* System Configuration Status Register */
+#define	OVCBIT		0x8000	/* b15-14: Over-current bit */
+#define	OVCMON		0xC000	/* b15-14: Over-current monitor */
+#define	SOFEA		0x0020	/* b5: SOF monitor */
+#define	IDMON		0x0004	/* b3: ID-pin monitor */
+#define	LNST		0x0003	/* b1-0: D+, D- line status */
+#define	  SE1		 0x0003	  /* SE1 */
+#define	  FS_KSTS	 0x0002	  /* Full-Speed K State */
+#define	  FS_JSTS	 0x0001	  /* Full-Speed J State */
+#define	  LS_JSTS	 0x0002	  /* Low-Speed J State */
+#define	  LS_KSTS	 0x0001	  /* Low-Speed K State */
+#define	  SE0		 0x0000	  /* SE0 */
+
+/* Device State Control Register */
+#define	EXTLP0		0x0400	/* b10: External port */
+#define	VBOUT		0x0200	/* b9: VBUS output */
+#define	WKUP		0x0100	/* b8: Remote wakeup */
+#define	RWUPE		0x0080	/* b7: Remote wakeup sense */
+#define	USBRST		0x0040	/* b6: USB reset enable */
+#define	RESUME		0x0020	/* b5: Resume enable */
+#define	UACT		0x0010	/* b4: USB bus enable */
+#define	RHST		0x0007	/* b1-0: Reset handshake status */
+#define	  HSPROC	 0x0004	  /* HS handshake is processing */
+#define	  HSMODE	 0x0003	  /* Hi-Speed mode */
+#define	  FSMODE	 0x0002	  /* Full-Speed mode */
+#define	  LSMODE	 0x0001	  /* Low-Speed mode */
+#define	  UNDECID	 0x0000	  /* Undecided */
+
+/* Test Mode Register */
+#define	UTST			0x000F	/* b3-0: Test select */
+#define	  H_TST_PACKET		 0x000C	  /* HOST TEST Packet */
+#define	  H_TST_SE0_NAK		 0x000B	  /* HOST TEST SE0 NAK */
+#define	  H_TST_K		 0x000A	  /* HOST TEST K */
+#define	  H_TST_J		 0x0009	  /* HOST TEST J */
+#define	  H_TST_NORMAL		 0x0000	  /* HOST Normal Mode */
+#define	  P_TST_PACKET		 0x0004	  /* PERI TEST Packet */
+#define	  P_TST_SE0_NAK		 0x0003	  /* PERI TEST SE0 NAK */
+#define	  P_TST_K		 0x0002	  /* PERI TEST K */
+#define	  P_TST_J		 0x0001	  /* PERI TEST J */
+#define	  P_TST_NORMAL		 0x0000	  /* PERI Normal Mode */
+
+/* Data Pin Configuration Register */
+#define	LDRV			0x8000	/* b15: Drive Current Adjust */
+#define	  VIF1			  0x0000		/* VIF = 1.8V */
+#define	  VIF3			  0x8000		/* VIF = 3.3V */
+#define	INTA			0x0001	/* b1: USB INT-pin active */
+
+/* DMAx Pin Configuration Register */
+#define	DREQA			0x4000	/* b14: Dreq active select */
+#define	BURST			0x2000	/* b13: Burst mode */
+#define	DACKA			0x0400	/* b10: Dack active select */
+#define	DFORM			0x0380	/* b9-7: DMA mode select */
+#define	  CPU_ADR_RD_WR		 0x0000	  /* Address + RD/WR mode (CPU bus) */
+#define	  CPU_DACK_RD_WR	 0x0100	  /* DACK + RD/WR mode (CPU bus) */
+#define	  CPU_DACK_ONLY		 0x0180	  /* DACK only mode (CPU bus) */
+#define	  SPLIT_DACK_ONLY	 0x0200	  /* DACK only mode (SPLIT bus) */
+#define	DENDA			0x0040	/* b6: Dend active select */
+#define	PKTM			0x0020	/* b5: Packet mode */
+#define	DENDE			0x0010	/* b4: Dend enable */
+#define	OBUS			0x0004	/* b2: OUTbus mode */
+
+/* CFIFO/DxFIFO Port Select Register */
+#define	RCNT		0x8000	/* b15: Read count mode */
+#define	REW		0x4000	/* b14: Buffer rewind */
+#define	DCLRM		0x2000	/* b13: DMA buffer clear mode */
+#define	DREQE		0x1000	/* b12: DREQ output enable */
+#define	  MBW_8		 0x0000	  /*  8bit */
+#define	  MBW_16	 0x0400	  /* 16bit */
+#define	  MBW_32	 0x0800   /* 32bit */
+#define	BIGEND		0x0100	/* b8: Big endian mode */
+#define	  BYTE_LITTLE	 0x0000		/* little dendian */
+#define	  BYTE_BIG	 0x0100		/* big endifan */
+#define	ISEL		0x0020	/* b5: DCP FIFO port direction select */
+#define	CURPIPE		0x000F	/* b2-0: PIPE select */
+
+/* CFIFO/DxFIFO Port Control Register */
+#define	BVAL		0x8000	/* b15: Buffer valid flag */
+#define	BCLR		0x4000	/* b14: Buffer clear */
+#define	FRDY		0x2000	/* b13: FIFO ready */
+#define	DTLN		0x0FFF	/* b11-0: FIFO received data length */
+
+/* Interrupt Enable Register 0 */
+#define	VBSE	0x8000	/* b15: VBUS interrupt */
+#define	RSME	0x4000	/* b14: Resume interrupt */
+#define	SOFE	0x2000	/* b13: Frame update interrupt */
+#define	DVSE	0x1000	/* b12: Device state transition interrupt */
+#define	CTRE	0x0800	/* b11: Control transfer stage transition interrupt */
+#define	BEMPE	0x0400	/* b10: Buffer empty interrupt */
+#define	NRDYE	0x0200	/* b9: Buffer not ready interrupt */
+#define	BRDYE	0x0100	/* b8: Buffer ready interrupt */
+
+/* Interrupt Enable Register 1 */
+#define	OVRCRE		0x8000	/* b15: Over-current interrupt */
+#define	BCHGE		0x4000	/* b14: USB us chenge interrupt */
+#define	DTCHE		0x1000	/* b12: Detach sense interrupt */
+#define	ATTCHE		0x0800	/* b11: Attach sense interrupt */
+#define	EOFERRE		0x0040	/* b6: EOF error interrupt */
+#define	SIGNE		0x0020	/* b5: SETUP IGNORE interrupt */
+#define	SACKE		0x0010	/* b4: SETUP ACK interrupt */
+
+/* BRDY Interrupt Enable/Status Register */
+#define	BRDY9		0x0200	/* b9: PIPE9 */
+#define	BRDY8		0x0100	/* b8: PIPE8 */
+#define	BRDY7		0x0080	/* b7: PIPE7 */
+#define	BRDY6		0x0040	/* b6: PIPE6 */
+#define	BRDY5		0x0020	/* b5: PIPE5 */
+#define	BRDY4		0x0010	/* b4: PIPE4 */
+#define	BRDY3		0x0008	/* b3: PIPE3 */
+#define	BRDY2		0x0004	/* b2: PIPE2 */
+#define	BRDY1		0x0002	/* b1: PIPE1 */
+#define	BRDY0		0x0001	/* b1: PIPE0 */
+
+/* NRDY Interrupt Enable/Status Register */
+#define	NRDY9		0x0200	/* b9: PIPE9 */
+#define	NRDY8		0x0100	/* b8: PIPE8 */
+#define	NRDY7		0x0080	/* b7: PIPE7 */
+#define	NRDY6		0x0040	/* b6: PIPE6 */
+#define	NRDY5		0x0020	/* b5: PIPE5 */
+#define	NRDY4		0x0010	/* b4: PIPE4 */
+#define	NRDY3		0x0008	/* b3: PIPE3 */
+#define	NRDY2		0x0004	/* b2: PIPE2 */
+#define	NRDY1		0x0002	/* b1: PIPE1 */
+#define	NRDY0		0x0001	/* b1: PIPE0 */
+
+/* BEMP Interrupt Enable/Status Register */
+#define	BEMP9		0x0200	/* b9: PIPE9 */
+#define	BEMP8		0x0100	/* b8: PIPE8 */
+#define	BEMP7		0x0080	/* b7: PIPE7 */
+#define	BEMP6		0x0040	/* b6: PIPE6 */
+#define	BEMP5		0x0020	/* b5: PIPE5 */
+#define	BEMP4		0x0010	/* b4: PIPE4 */
+#define	BEMP3		0x0008	/* b3: PIPE3 */
+#define	BEMP2		0x0004	/* b2: PIPE2 */
+#define	BEMP1		0x0002	/* b1: PIPE1 */
+#define	BEMP0		0x0001	/* b0: PIPE0 */
+
+/* SOF Pin Configuration Register */
+#define	TRNENSEL	0x0100	/* b8: Select transaction enable period */
+#define	BRDYM		0x0040	/* b6: BRDY clear timing */
+#define	INTL		0x0020	/* b5: Interrupt sense select */
+#define	EDGESTS		0x0010	/* b4:  */
+#define	SOFMODE		0x000C	/* b3-2: SOF pin select */
+#define	  SOF_125US	 0x0008	  /* SOF OUT 125us Frame Signal */
+#define	  SOF_1MS	 0x0004	  /* SOF OUT 1ms Frame Signal */
+#define	  SOF_DISABLE	 0x0000	  /* SOF OUT Disable */
+
+/* Interrupt Status Register 0 */
+#define	VBINT	0x8000	/* b15: VBUS interrupt */
+#define	RESM	0x4000	/* b14: Resume interrupt */
+#define	SOFR	0x2000	/* b13: SOF frame update interrupt */
+#define	DVST	0x1000	/* b12: Device state transition interrupt */
+#define	CTRT	0x0800	/* b11: Control transfer stage transition interrupt */
+#define	BEMP	0x0400	/* b10: Buffer empty interrupt */
+#define	NRDY	0x0200	/* b9: Buffer not ready interrupt */
+#define	BRDY	0x0100	/* b8: Buffer ready interrupt */
+#define	VBSTS	0x0080	/* b7: VBUS input port */
+#define	DVSQ	0x0070	/* b6-4: Device state */
+#define	  DS_SPD_CNFG	 0x0070	  /* Suspend Configured */
+#define	  DS_SPD_ADDR	 0x0060	  /* Suspend Address */
+#define	  DS_SPD_DFLT	 0x0050	  /* Suspend Default */
+#define	  DS_SPD_POWR	 0x0040	  /* Suspend Powered */
+#define	  DS_SUSP	 0x0040	  /* Suspend */
+#define	  DS_CNFG	 0x0030	  /* Configured */
+#define	  DS_ADDS	 0x0020	  /* Address */
+#define	  DS_DFLT	 0x0010	  /* Default */
+#define	  DS_POWR	 0x0000	  /* Powered */
+#define	DVSQS		0x0030	/* b5-4: Device state */
+#define	VALID		0x0008	/* b3: Setup packet detected flag */
+#define	CTSQ		0x0007	/* b2-0: Control transfer stage */
+#define	  CS_SQER	 0x0006	  /* Sequence error */
+#define	  CS_WRND	 0x0005	  /* Control write nodata status stage */
+#define	  CS_WRSS	 0x0004	  /* Control write status stage */
+#define	  CS_WRDS	 0x0003	  /* Control write data stage */
+#define	  CS_RDSS	 0x0002	  /* Control read status stage */
+#define	  CS_RDDS	 0x0001	  /* Control read data stage */
+#define	  CS_IDST	 0x0000	  /* Idle or setup stage */
+
+/* Interrupt Status Register 1 */
+#define	OVRCR		0x8000	/* b15: Over-current interrupt */
+#define	BCHG		0x4000	/* b14: USB bus chenge interrupt */
+#define	DTCH		0x1000	/* b12: Detach sense interrupt */
+#define	ATTCH		0x0800	/* b11: Attach sense interrupt */
+#define	EOFERR		0x0040	/* b6: EOF-error interrupt */
+#define	SIGN		0x0020	/* b5: Setup ignore interrupt */
+#define	SACK		0x0010	/* b4: Setup acknowledge interrupt */
+
+/* Frame Number Register */
+#define	OVRN		0x8000	/* b15: Overrun error */
+#define	CRCE		0x4000	/* b14: Received data error */
+#define	FRNM		0x07FF	/* b10-0: Frame number */
+
+/* Micro Frame Number Register */
+#define	UFRNM		0x0007	/* b2-0: Micro frame number */
+
+/* Default Control Pipe Maxpacket Size Register */
+/* Pipe Maxpacket Size Register */
+#define	DEVSEL	0xF000	/* b15-14: Device address select */
+#define	MAXP	0x007F	/* b6-0: Maxpacket size of default control pipe */
+
+/* Default Control Pipe Control Register */
+#define	BSTS		0x8000	/* b15: Buffer status */
+#define	SUREQ		0x4000	/* b14: Send USB request  */
+#define	CSCLR		0x2000	/* b13: complete-split status clear */
+#define	CSSTS		0x1000	/* b12: complete-split status */
+#define	SUREQCLR	0x0800	/* b11: stop setup request */
+#define	SQCLR		0x0100	/* b8: Sequence toggle bit clear */
+#define	SQSET		0x0080	/* b7: Sequence toggle bit set */
+#define	SQMON		0x0040	/* b6: Sequence toggle bit monitor */
+#define	PBUSY		0x0020	/* b5: pipe busy */
+#define	PINGE		0x0010	/* b4: ping enable */
+#define	CCPL		0x0004	/* b2: Enable control transfer complete */
+#define	PID		0x0003	/* b1-0: Response PID */
+#define	  PID_STALL11	 0x0003	  /* STALL */
+#define	  PID_STALL	 0x0002	  /* STALL */
+#define	  PID_BUF	 0x0001	  /* BUF */
+#define	  PID_NAK	 0x0000	  /* NAK */
+
+/* Pipe Window Select Register */
+#define	PIPENM		0x0007	/* b2-0: Pipe select */
+
+/* Pipe Configuration Register */
+#define	R8A66597_TYP	0xC000	/* b15-14: Transfer type */
+#define	  R8A66597_ISO	 0xC000		  /* Isochronous */
+#define	  R8A66597_INT	 0x8000		  /* Interrupt */
+#define	  R8A66597_BULK	 0x4000		  /* Bulk */
+#define	R8A66597_BFRE	0x0400	/* b10: Buffer ready interrupt mode select */
+#define	R8A66597_DBLB	0x0200	/* b9: Double buffer mode select */
+#define	R8A66597_CNTMD	0x0100	/* b8: Continuous transfer mode select */
+#define	R8A66597_SHTNAK	0x0080	/* b7: Transfer end NAK */
+#define	R8A66597_DIR	0x0010	/* b4: Transfer direction select */
+#define	R8A66597_EPNUM	0x000F	/* b3-0: Eendpoint number select */
+
+/* Pipe Buffer Configuration Register */
+#define	BUFSIZE		0x7C00	/* b14-10: Pipe buffer size */
+#define	BUFNMB		0x007F	/* b6-0: Pipe buffer number */
+#define	PIPE0BUF	256
+#define	PIPExBUF	64
+
+/* Pipe Maxpacket Size Register */
+#define	MXPS		0x07FF	/* b10-0: Maxpacket size */
+
+/* Pipe Cycle Configuration Register */
+#define	IFIS	0x1000	/* b12: Isochronous in-buffer flush mode select */
+#define	IITV	0x0007	/* b2-0: Isochronous interval */
+
+/* Pipex Control Register */
+#define	BSTS	0x8000	/* b15: Buffer status */
+#define	INBUFM	0x4000	/* b14: IN buffer monitor (Only for PIPE1 to 5) */
+#define	CSCLR	0x2000	/* b13: complete-split status clear */
+#define	CSSTS	0x1000	/* b12: complete-split status */
+#define	ATREPM	0x0400	/* b10: Auto repeat mode */
+#define	ACLRM	0x0200	/* b9: Out buffer auto clear mode */
+#define	SQCLR	0x0100	/* b8: Sequence toggle bit clear */
+#define	SQSET	0x0080	/* b7: Sequence toggle bit set */
+#define	SQMON	0x0040	/* b6: Sequence toggle bit monitor */
+#define	PBUSY	0x0020	/* b5: pipe busy */
+#define	PID	0x0003	/* b1-0: Response PID */
+
+/* PIPExTRE */
+#define	TRENB		0x0200	/* b9: Transaction counter enable */
+#define	TRCLR		0x0100	/* b8: Transaction counter clear */
+
+/* PIPExTRN */
+#define	TRNCNT		0xFFFF	/* b15-0: Transaction counter */
+
+/* DEVADDx */
+#define	UPPHUB		0x7800
+#define	HUBPORT		0x0700
+#define	USBSPD		0x00C0
+#define	RTPORT		0x0001
+
+#endif /* __LINUX_USB_R8A66597_H */