Merge git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6: (187 commits)
  sh: remove dead LED code for migo-r and ms7724se
  sh: ecovec build fix for CONFIG_I2C=n
  sh: ecovec r-standby support
  sh: ms7724se r-standby support
  sh: SH-Mobile R-standby register save/restore
  clocksource: Fix up a registration/IRQ race in the sh drivers.
  sh: ms7724: modify scan_timing for KEYSC
  sh: ms7724: Add sh_sir support
  sh: mach-ecovec24: Add sh_sir support
  sh: wire up SET/GET_UNALIGN_CTL.
  sh: allow alignment fault mode to be configured at kernel boot.
  sh: sh7724: Update FSI/SPU2 clock
  sh: always enable sh7724 vpu_clk and set to 166MHz on Ecovec
  sh: add sh7724 kick callback to clk_div4_table
  sh: introduce struct clk_div4_table
  sh: clock-cpg div4 set_rate() shift fix
  sh: Turn on speculative return for SH7785 and SH7786
  sh: Merge legacy and dynamic PMB modes.
  sh: Use uncached I/O helpers in PMB setup.
  sh: Provide uncached I/O helpers.
  ...
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 2121fbb..05cef50 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -13,7 +13,6 @@
 	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_DMA_ATTRS
@@ -22,6 +21,7 @@
 	select HAVE_KERNEL_GZIP
 	select HAVE_KERNEL_BZIP2
 	select HAVE_KERNEL_LZMA
+	select HAVE_KERNEL_LZO
 	select HAVE_SYSCALL_TRACEPOINTS
 	select RTC_LIB
 	select GENERIC_ATOMIC64
@@ -35,6 +35,7 @@
 	def_bool ARCH = "sh"
 	select HAVE_KPROBES
 	select HAVE_KRETPROBES
+	select HAVE_IOREMAP_PROT if MMU && !X2TLB
 	select HAVE_FUNCTION_TRACER
 	select HAVE_FTRACE_MCOUNT_RECORD
 	select HAVE_DYNAMIC_FTRACE
@@ -42,6 +43,8 @@
 	select HAVE_FTRACE_NMI_ENTER if DYNAMIC_FTRACE
 	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_ARCH_KGDB
+	select HAVE_HW_BREAKPOINT
+	select PERF_EVENTS if HAVE_HW_BREAKPOINT
 	select ARCH_HIBERNATION_POSSIBLE if MMU
 
 config SUPERH64
@@ -78,12 +81,13 @@
 config GENERIC_HARDIRQS_NO__DO_IRQ
 	def_bool y
 
-config GENERIC_IRQ_PROBE
-	def_bool y
-
 config IRQ_PER_CPU
 	def_bool y
 
+config SPARSE_IRQ
+	def_bool y
+	depends on SUPERH32
+
 config GENERIC_GPIO
 	def_bool n
 
@@ -548,8 +552,7 @@
 			      CPU_SUBTYPE_SH7203 || \
 			      CPU_SUBTYPE_SH7206 || \
 			      CPU_SUBTYPE_SH7263 || \
-			      CPU_SUBTYPE_MXG    || \
-			      CPU_SUBTYPE_SH7786
+			      CPU_SUBTYPE_MXG
 	default "60000000" if CPU_SUBTYPE_SH7751 || CPU_SUBTYPE_SH7751R
 	default "66000000" if CPU_SUBTYPE_SH4_202
 	default "50000000"
@@ -563,7 +566,8 @@
 
 config SH_CLK_CPG_LEGACY
 	depends on SH_CLK_CPG
-	def_bool y if !CPU_SUBTYPE_SH7785 && !ARCH_SHMOBILE
+	def_bool y if !CPU_SUBTYPE_SH7785 && !ARCH_SHMOBILE && \
+		      !CPU_SUBTYPE_SH7786
 
 config SH_CLK_MD
 	int "CPU Mode Pin Setting"
@@ -725,18 +729,6 @@
 	  LLSC, this should be more efficient than the other alternative of
 	  disabling interrupts around the atomic sequence.
 
-config SPARSE_IRQ
-	bool "Support sparse irq numbering"
-	depends on EXPERIMENTAL
-	help
-	  This enables support for sparse irqs. This is useful in general
-	  as most CPUs have a fairly sparse array of IRQ vectors, which
-	  the irq_desc then maps directly on to. Systems with a high
-	  number of off-chip IRQs will want to treat this as
-	  experimental until they have been independently verified.
-
-	  If you don't know what to do here, say N.
-
 endmenu
 
 menu "Boot options"
@@ -822,11 +814,15 @@
 config PCI
 	bool "PCI support"
 	depends on SYS_SUPPORTS_PCI
+	select PCI_DOMAINS
 	help
 	  Find out whether you have a PCI motherboard. PCI is the name of a
 	  bus system, i.e. the way the CPU talks to the other stuff inside
 	  your box. If you have PCI, say Y, otherwise N.
 
+config PCI_DOMAINS
+	bool
+
 source "drivers/pci/pcie/Kconfig"
 
 source "drivers/pci/Kconfig"
diff --git a/arch/sh/Kconfig.cpu b/arch/sh/Kconfig.cpu
index cd6e3ea..ddf096c 100644
--- a/arch/sh/Kconfig.cpu
+++ b/arch/sh/Kconfig.cpu
@@ -68,7 +68,8 @@
 
 config SPECULATIVE_EXECUTION
 	bool "Speculative subroutine return"
-	depends on CPU_SUBTYPE_SH7780 && EXPERIMENTAL
+	depends on EXPERIMENTAL
+	depends on CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785 || CPU_SUBTYPE_SH7786
 	help
 	  This enables support for a speculative instruction fetch for
 	  subroutine return. There are various pitfalls associated with
diff --git a/arch/sh/Makefile b/arch/sh/Makefile
index db91925..588579a 100644
--- a/arch/sh/Makefile
+++ b/arch/sh/Makefile
@@ -83,6 +83,7 @@
 defaultimage-$(CONFIG_SH_7724_SOLUTION_ENGINE)	:= uImage
 defaultimage-$(CONFIG_SH_7206_SOLUTION_ENGINE)	:= vmlinux
 defaultimage-$(CONFIG_SH_7619_SOLUTION_ENGINE)	:= vmlinux
+defaultimage-$(CONFIG_SH_SDK7786)		:= vmlinux.bin
 
 # Set some sensible Kbuild defaults
 KBUILD_IMAGE		:= $(defaultimage-y)
@@ -143,11 +144,11 @@
 machdir-$(CONFIG_SH_KFR2R09)			+= mach-kfr2r09
 machdir-$(CONFIG_SH_ECOVEC)			+= mach-ecovec24
 machdir-$(CONFIG_SH_SDK7780)			+= mach-sdk7780
+machdir-$(CONFIG_SH_SDK7786)			+= mach-sdk7786
 machdir-$(CONFIG_SH_X3PROTO)			+= mach-x3proto
 machdir-$(CONFIG_SH_SH7763RDP)			+= mach-sh7763rdp
 machdir-$(CONFIG_SH_SH4202_MICRODEV)		+= mach-microdev
 machdir-$(CONFIG_SH_LANDISK)			+= mach-landisk
-machdir-$(CONFIG_SH_TITAN)			+= mach-titan
 machdir-$(CONFIG_SH_LBOX_RE2)			+= mach-lboxre2
 machdir-$(CONFIG_SH_CAYMAN)			+= mach-cayman
 machdir-$(CONFIG_SH_RSK)			+= mach-rsk
@@ -203,8 +204,9 @@
 libs-$(CONFIG_SUPERH32)		:= arch/sh/lib/	$(libs-y)
 libs-$(CONFIG_SUPERH64)		:= arch/sh/lib64/ $(libs-y)
 
-BOOT_TARGETS = uImage uImage.bz2 uImage.gz uImage.lzma uImage.srec uImage.bin \
-	       zImage vmlinux.srec romImage
+BOOT_TARGETS = uImage uImage.bz2 uImage.gz uImage.lzma uImage.lzo \
+	       uImage.srec uImage.bin zImage vmlinux.bin vmlinux.srec \
+	       romImage
 PHONY += $(BOOT_TARGETS)
 
 all: $(KBUILD_IMAGE)
@@ -225,10 +227,12 @@
 	@echo '  zImage 	           - Compressed kernel image'
 	@echo '  romImage	           - Compressed ROM image, if supported'
 	@echo '  vmlinux.srec	           - Create an ELF S-record'
+	@echo '  vmlinux.bin	           - Create an uncompressed binary image'
 	@echo '* uImage  	           - Alias to bootable U-Boot image'
 	@echo '  uImage.srec	           - Create an S-record for U-Boot'
 	@echo '  uImage.bin	           - Kernel-only image for U-Boot (bin)'
 	@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)'
+	@echo '  uImage.lzo	           - Kernel-only image for U-Boot (lzo)'
 endef
diff --git a/arch/sh/boards/Kconfig b/arch/sh/boards/Kconfig
index aedd9de..938e87d 100644
--- a/arch/sh/boards/Kconfig
+++ b/arch/sh/boards/Kconfig
@@ -150,6 +150,14 @@
 	  Select SDK7780 if configuring for a Renesas SH7780 SDK7780R3
 	  evaluation board.
 
+config SH_SDK7786
+	bool "SDK7786"
+	depends on CPU_SUBTYPE_SH7786
+	select SYS_SUPPORTS_PCI
+	help
+	  Select SDK7786 if configuring for a Renesas Technology Europe
+	  SH7786-65nm board.
+
 config SH_HIGHLANDER
 	bool "Highlander"
 	depends on CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785
diff --git a/arch/sh/boards/Makefile b/arch/sh/boards/Makefile
index ce0f263..4f90f9b 100644
--- a/arch/sh/boards/Makefile
+++ b/arch/sh/boards/Makefile
@@ -8,3 +8,4 @@
 obj-$(CONFIG_SH_EDOSK7760)	+= board-edosk7760.o
 obj-$(CONFIG_SH_ESPT)		+= board-espt.o
 obj-$(CONFIG_SH_POLARIS)	+= board-polaris.o
+obj-$(CONFIG_SH_TITAN)		+= board-titan.o
diff --git a/arch/sh/boards/board-magicpanelr2.c b/arch/sh/boards/board-magicpanelr2.c
index 99ffc5f..efba450 100644
--- a/arch/sh/boards/board-magicpanelr2.c
+++ b/arch/sh/boards/board-magicpanelr2.c
@@ -23,7 +23,7 @@
 #include <asm/heartbeat.h>
 #include <cpu/sh7720.h>
 
-#define LAN9115_READY	(ctrl_inl(0xA8000084UL) & 0x00000001UL)
+#define LAN9115_READY	(__raw_readl(0xA8000084UL) & 0x00000001UL)
 
 /* Prefer cmdline over RedBoot */
 static const char *probes[] = { "cmdlinepart", "RedBoot", NULL };
@@ -60,33 +60,33 @@
 {
 	/* CS2: LAN (0x08000000 - 0x0bffffff) */
 	/* no idle cycles, normal space, 8 bit data bus */
-	ctrl_outl(0x36db0400, CS2BCR);
+	__raw_writel(0x36db0400, CS2BCR);
 	/* (SW:1.5 WR:3 HW:1.5), ext. wait */
-	ctrl_outl(0x000003c0, CS2WCR);
+	__raw_writel(0x000003c0, CS2WCR);
 
 	/* CS4: CAN1 (0xb0000000 - 0xb3ffffff) */
 	/* no idle cycles, normal space, 8 bit data bus */
-	ctrl_outl(0x00000200, CS4BCR);
+	__raw_writel(0x00000200, CS4BCR);
 	/* (SW:1.5 WR:3 HW:1.5), ext. wait */
-	ctrl_outl(0x00100981, CS4WCR);
+	__raw_writel(0x00100981, CS4WCR);
 
 	/* CS5a: CAN2 (0xb4000000 - 0xb5ffffff) */
 	/* no idle cycles, normal space, 8 bit data bus */
-	ctrl_outl(0x00000200, CS5ABCR);
+	__raw_writel(0x00000200, CS5ABCR);
 	/* (SW:1.5 WR:3 HW:1.5), ext. wait */
-	ctrl_outl(0x00100981, CS5AWCR);
+	__raw_writel(0x00100981, CS5AWCR);
 
 	/* CS5b: CAN3 (0xb6000000 - 0xb7ffffff) */
 	/* no idle cycles, normal space, 8 bit data bus */
-	ctrl_outl(0x00000200, CS5BBCR);
+	__raw_writel(0x00000200, CS5BBCR);
 	/* (SW:1.5 WR:3 HW:1.5), ext. wait */
-	ctrl_outl(0x00100981, CS5BWCR);
+	__raw_writel(0x00100981, CS5BWCR);
 
 	/* CS6a: Rotary (0xb8000000 - 0xb9ffffff) */
 	/* no idle cycles, normal space, 8 bit data bus */
-	ctrl_outl(0x00000200, CS6ABCR);
+	__raw_writel(0x00000200, CS6ABCR);
 	/* (SW:1.5 WR:3 HW:1.5), no ext. wait */
-	ctrl_outl(0x001009C1, CS6AWCR);
+	__raw_writel(0x001009C1, CS6AWCR);
 }
 
 static void __init setup_port_multiplexing(void)
@@ -94,71 +94,71 @@
 	/* A7 GPO(LED8);     A6 GPO(LED7);     A5 GPO(LED6);	  A4 GPO(LED5);
 	 * A3 GPO(LED4);     A2 GPO(LED3);     A1 GPO(LED2);	  A0 GPO(LED1);
 	 */
-	ctrl_outw(0x5555, PORT_PACR);	/* 01 01 01 01 01 01 01 01 */
+	__raw_writew(0x5555, PORT_PACR);	/* 01 01 01 01 01 01 01 01 */
 
 	/* B7 GPO(RST4);   B6 GPO(RST3);  B5 GPO(RST2);    B4 GPO(RST1);
 	 * B3 GPO(PB3);	   B2 GPO(PB2);	  B1 GPO(PB1);	   B0 GPO(PB0);
 	 */
-	ctrl_outw(0x5555, PORT_PBCR);	/* 01 01 01 01 01 01 01 01 */
+	__raw_writew(0x5555, PORT_PBCR);	/* 01 01 01 01 01 01 01 01 */
 
 	/* C7 GPO(PC7);	  C6 GPO(PC6);	  C5 GPO(PC5);	   C4 GPO(PC4);
 	 * C3 LCD_DATA3;  C2 LCD_DATA2;   C1 LCD_DATA1;	   C0 LCD_DATA0;
 	 */
-	ctrl_outw(0x5500, PORT_PCCR);	/* 01 01 01 01 00 00 00 00 */
+	__raw_writew(0x5500, PORT_PCCR);	/* 01 01 01 01 00 00 00 00 */
 
 	/* D7 GPO(PD7);	D6 GPO(PD6);	D5 GPO(PD5);	   D4 GPO(PD4);
 	 * D3 GPO(PD3);	D2 GPO(PD2);	D1 GPO(PD1);	   D0 GPO(PD0);
 	 */
-	ctrl_outw(0x5555, PORT_PDCR);	/* 01 01 01 01 01 01 01 01 */
+	__raw_writew(0x5555, PORT_PDCR);	/* 01 01 01 01 01 01 01 01 */
 
 	/* E7 (x);	  E6 GPI(nu);	 E5 GPI(nu);	  E4 LCD_M_DISP;
 	 * E3 LCD_CL1;	  E2 LCD_CL2;	 E1 LCD_DON;	  E0 LCD_FLM;
 	 */
-	ctrl_outw(0x3C00, PORT_PECR);	/* 00 11 11 00 00 00 00 00 */
+	__raw_writew(0x3C00, PORT_PECR);	/* 00 11 11 00 00 00 00 00 */
 
 	/* F7 (x);	     F6 DA1(VLCD);     F5 DA0(nc);	  F4 AN3;
 	 * F3 AN2(MID_AD);   F2 AN1(EARTH_AD); F1 AN0(TEMP);	  F0 GPI+(nc);
 	 */
-	ctrl_outw(0x0002, PORT_PFCR);	/* 00 00 00 00 00 00 00 10 */
+	__raw_writew(0x0002, PORT_PFCR);	/* 00 00 00 00 00 00 00 10 */
 
 	/* G7 (x);	  G6 IRQ5(TOUCH_BUSY); G5 IRQ4(TOUCH_IRQ); G4 GPI(KEY2);
 	 * G3 GPI(KEY1);  G2 GPO(LED11);	G1 GPO(LED10);     G0 GPO(LED9);
 	 */
-	ctrl_outw(0x03D5, PORT_PGCR);	/* 00 00 00 11 11 01 01 01 */
+	__raw_writew(0x03D5, PORT_PGCR);	/* 00 00 00 11 11 01 01 01 */
 
 	/* H7 (x);	      H6 /RAS(BRAS);	  H5 /CAS(BCAS); H4 CKE(BCKE);
 	 * H3 GPO(EARTH_OFF); H2 GPO(EARTH_TEST); H1 USB2_PWR;	 H0 USB1_PWR;
 	 */
-	ctrl_outw(0x0050, PORT_PHCR);	/* 00 00 00 00 01 01 00 00 */
+	__raw_writew(0x0050, PORT_PHCR);	/* 00 00 00 00 01 01 00 00 */
 
 	/* J7 (x);	  J6 AUDCK;	   J5 ASEBRKAK;	    J4 AUDATA3;
 	 * J3 AUDATA2;	  J2 AUDATA1;	   J1 AUDATA0;	    J0 AUDSYNC;
 	 */
-	ctrl_outw(0x0000, PORT_PJCR);	/* 00 00 00 00 00 00 00 00 */
+	__raw_writew(0x0000, PORT_PJCR);	/* 00 00 00 00 00 00 00 00 */
 
 	/* K7 (x);	    K6 (x);	     K5 (x);	   K4 (x);
 	 * K3 PINT7(/PWR2); K2 PINT6(/PWR1); K1 PINT5(nu); K0 PINT4(FLASH_READY)
 	 */
-	ctrl_outw(0x00FF, PORT_PKCR);	/* 00 00 00 00 11 11 11 11 */
+	__raw_writew(0x00FF, PORT_PKCR);	/* 00 00 00 00 11 11 11 11 */
 
 	/* L7 TRST;	   L6 TMS;	     L5 TDO;		  L4 TDI;
 	 * L3 TCK;	   L2 (x);	     L1 (x);		  L0 (x);
 	 */
-	ctrl_outw(0x0000, PORT_PLCR);	/* 00 00 00 00 00 00 00 00 */
+	__raw_writew(0x0000, PORT_PLCR);	/* 00 00 00 00 00 00 00 00 */
 
 	/* M7 GPO(CURRENT_SINK);    M6 GPO(PWR_SWITCH);     M5 GPO(LAN_SPEED);
 	 * M4 GPO(LAN_RESET);       M3 GPO(BUZZER);	    M2 GPO(LCD_BL);
 	 * M1 CS5B(CAN3_CS);	    M0 GPI+(nc);
 	 */
-	ctrl_outw(0x5552, PORT_PMCR);	   /* 01 01 01 01 01 01 00 10 */
+	__raw_writew(0x5552, PORT_PMCR);	   /* 01 01 01 01 01 01 00 10 */
 
 	/* CURRENT_SINK=off,	PWR_SWITCH=off, LAN_SPEED=100MBit,
 	 * LAN_RESET=off,	BUZZER=off,	LCD_BL=off
 	 */
 #if CONFIG_SH_MAGIC_PANEL_R2_VERSION == 2
-	ctrl_outb(0x30, PORT_PMDR);
+	__raw_writeb(0x30, PORT_PMDR);
 #elif CONFIG_SH_MAGIC_PANEL_R2_VERSION == 3
-	ctrl_outb(0xF0, PORT_PMDR);
+	__raw_writeb(0xF0, PORT_PMDR);
 #else
 #error Unknown revision of PLATFORM_MP_R2
 #endif
@@ -167,8 +167,8 @@
 	 * P4 GPO(nu);	       P3 IRQ3(LAN_IRQ);  P2 IRQ2(CAN3_IRQ);
 	 * P1 IRQ1(CAN2_IRQ);  P0 IRQ0(CAN1_IRQ)
 	 */
-	ctrl_outw(0x0100, PORT_PPCR);	/* 00 00 00 01 00 00 00 00 */
-	ctrl_outb(0x10, PORT_PPDR);
+	__raw_writew(0x0100, PORT_PPCR);	/* 00 00 00 01 00 00 00 00 */
+	__raw_writeb(0x10, PORT_PPDR);
 
 	/* R7 A25;	     R6 A24;	     R5 A23;		  R4 A22;
 	 * R3 A21;	     R2 A20;	     R1 A19;		  R0 A0;
@@ -185,22 +185,22 @@
 	/* S7 (x);		S6 (x);        S5 (x);	     S4 GPO(EEPROM_CS2);
 	 * S3 GPO(EEPROM_CS1);  S2 SIOF0_TXD;  S1 SIOF0_RXD; S0 SIOF0_SCK;
 	 */
-	ctrl_outw(0x0140, PORT_PSCR);	/* 00 00 00 01 01 00 00 00 */
+	__raw_writew(0x0140, PORT_PSCR);	/* 00 00 00 01 01 00 00 00 */
 
 	/* T7 (x);	   T6 (x);	  T5 (x);	  T4 COM1_CTS;
 	 * T3 COM1_RTS;	   T2 COM1_TXD;	  T1 COM1_RXD;	  T0 GPO(WDOG)
 	 */
-	ctrl_outw(0x0001, PORT_PTCR);	/* 00 00 00 00 00 00 00 01 */
+	__raw_writew(0x0001, PORT_PTCR);	/* 00 00 00 00 00 00 00 01 */
 
 	/* U7 (x);	     U6 (x);	   U5 (x);	  U4 GPI+(/AC_FAULT);
 	 * U3 GPO(TOUCH_CS); U2 TOUCH_TXD; U1 TOUCH_RXD;  U0 TOUCH_SCK;
 	 */
-	ctrl_outw(0x0240, PORT_PUCR);	/* 00 00 00 10 01 00 00 00 */
+	__raw_writew(0x0240, PORT_PUCR);	/* 00 00 00 10 01 00 00 00 */
 
 	/* V7 (x);	  V6 (x);	V5 (x);		  V4 GPO(MID2);
 	 * V3 GPO(MID1);  V2 CARD_TxD;	V1 CARD_RxD;	  V0 GPI+(/BAT_FAULT);
 	 */
-	ctrl_outw(0x0142, PORT_PVCR);	/* 00 00 00 01 01 00 00 10 */
+	__raw_writew(0x0142, PORT_PVCR);	/* 00 00 00 01 01 00 00 10 */
 }
 
 static void __init mpr2_setup(char **cmdline_p)
@@ -209,24 +209,24 @@
 	 * /PCC_CD1, /PCC_CD2,  PCC_BVD1, PCC_BVD2,
 	 * /IOIS16,  IRQ4,	IRQ5,	  USB1d_SUSPEND
 	 */
-	ctrl_outw(0xAABC, PORT_PSELA);
+	__raw_writew(0xAABC, PORT_PSELA);
 	/* set Pin Select Register B:
 	 * /SCIF0_RTS, /SCIF0_CTS, LCD_VCPWC,
 	 * LCD_VEPWC,  IIC_SDA,    IIC_SCL, Reserved
 	 */
-	ctrl_outw(0x3C00, PORT_PSELB);
+	__raw_writew(0x3C00, PORT_PSELB);
 	/* set Pin Select Register C:
 	 * SIOF1_SCK, SIOF1_RxD, SCIF1_RxD, SCIF1_TxD, Reserved
 	 */
-	ctrl_outw(0x0000, PORT_PSELC);
+	__raw_writew(0x0000, PORT_PSELC);
 	/* set Pin Select Register D: Reserved, SIOF1_TxD, Reserved, SIOF1_MCLK,
 	 * Reserved, SIOF1_SYNC, Reserved, SCIF1_SCK, Reserved
 	 */
-	ctrl_outw(0x0000, PORT_PSELD);
+	__raw_writew(0x0000, PORT_PSELD);
 	/* set USB TxRx Control: Reserved, DRV, Reserved, USB_TRANS, USB_SEL */
-	ctrl_outw(0x0101, PORT_UTRCTL);
+	__raw_writew(0x0101, PORT_UTRCTL);
 	/* set USB Clock Control: USSCS, USSTB, Reserved (HighByte always A5) */
-	ctrl_outw(0xA5C0, PORT_UCLKCR_W);
+	__raw_writew(0xA5C0, PORT_UCLKCR_W);
 
 	setup_chip_select();
 
diff --git a/arch/sh/boards/board-polaris.c b/arch/sh/boards/board-polaris.c
index 62607eb..5948663 100644
--- a/arch/sh/boards/board-polaris.c
+++ b/arch/sh/boards/board-polaris.c
@@ -59,15 +59,12 @@
 static struct heartbeat_data heartbeat_data = {
 	.bit_pos	= heartbeat_bit_pos,
 	.nr_bits	= ARRAY_SIZE(heartbeat_bit_pos),
-	.regsize	= 8,
 };
 
-static struct resource heartbeat_resources[] = {
-	[0] = {
-		.start	= PORT_PCDR,
-		.end	= PORT_PCDR,
-		.flags	= IORESOURCE_MEM,
-	},
+static struct resource heartbeat_resource = {
+	.start	= PORT_PCDR,
+	.end	= PORT_PCDR,
+	.flags	= IORESOURCE_MEM | IORESOURCE_MEM_8BIT,
 };
 
 static struct platform_device heartbeat_device = {
@@ -76,8 +73,8 @@
 	.dev	= {
 		.platform_data	= &heartbeat_data,
 	},
-	.num_resources	= ARRAY_SIZE(heartbeat_resources),
-	.resource	= heartbeat_resources,
+	.num_resources	= 1,
+	.resource	= &heartbeat_resource,
 };
 
 static struct platform_device *polaris_devices[] __initdata = {
@@ -92,15 +89,15 @@
 	printk(KERN_INFO "Configuring Polaris external bus\n");
 
 	/* Configure area 5 with 2 wait states */
-	wcr = ctrl_inw(WCR2);
+	wcr = __raw_readw(WCR2);
 	wcr &= (~AREA5_WAIT_CTRL);
 	wcr |= (WAIT_STATES_10 << 10);
-	ctrl_outw(wcr, WCR2);
+	__raw_writew(wcr, WCR2);
 
 	/* Configure area 5 for 32-bit access */
-	bcr_mask = ctrl_inw(BCR2);
+	bcr_mask = __raw_readw(BCR2);
 	bcr_mask |= 1 << 10;
-	ctrl_outw(bcr_mask, BCR2);
+	__raw_writew(bcr_mask, BCR2);
 
 	return platform_add_devices(polaris_devices,
 				    ARRAY_SIZE(polaris_devices));
@@ -131,13 +128,13 @@
 static void __init init_polaris_irq(void)
 {
 	/* Disable all interrupts */
-	ctrl_outw(0, BCR_ILCRA);
-	ctrl_outw(0, BCR_ILCRB);
-	ctrl_outw(0, BCR_ILCRC);
-	ctrl_outw(0, BCR_ILCRD);
-	ctrl_outw(0, BCR_ILCRE);
-	ctrl_outw(0, BCR_ILCRF);
-	ctrl_outw(0, BCR_ILCRG);
+	__raw_writew(0, BCR_ILCRA);
+	__raw_writew(0, BCR_ILCRB);
+	__raw_writew(0, BCR_ILCRC);
+	__raw_writew(0, BCR_ILCRD);
+	__raw_writew(0, BCR_ILCRE);
+	__raw_writew(0, BCR_ILCRF);
+	__raw_writew(0, BCR_ILCRG);
 
 	register_ipr_controller(&ipr_irq_desc);
 }
diff --git a/arch/sh/boards/board-sh7785lcr.c b/arch/sh/boards/board-sh7785lcr.c
index e5a8a2f..fe7e686 100644
--- a/arch/sh/boards/board-sh7785lcr.c
+++ b/arch/sh/boards/board-sh7785lcr.c
@@ -21,6 +21,7 @@
 #include <linux/i2c-algo-pca.h>
 #include <linux/usb/r8a66597.h>
 #include <linux/irq.h>
+#include <linux/io.h>
 #include <linux/clk.h>
 #include <linux/errno.h>
 #include <mach/sh7785lcr.h>
@@ -32,26 +33,17 @@
  * NOTE: This board has 2 physical memory maps.
  *	 Please look at include/asm-sh/sh7785lcr.h or hardware manual.
  */
-static struct resource heartbeat_resources[] = {
-	[0] = {
-		.start	= PLD_LEDCR,
-		.end	= PLD_LEDCR,
-		.flags	= IORESOURCE_MEM,
-	},
-};
-
-static struct heartbeat_data heartbeat_data = {
-	.regsize = 8,
+static struct resource heartbeat_resource = {
+	.start	= PLD_LEDCR,
+	.end	= PLD_LEDCR,
+	.flags	= IORESOURCE_MEM | IORESOURCE_MEM_8BIT,
 };
 
 static struct platform_device heartbeat_device = {
 	.name		= "heartbeat",
 	.id		= -1,
-	.dev	= {
-		.platform_data	= &heartbeat_data,
-	},
-	.num_resources	= ARRAY_SIZE(heartbeat_resources),
-	.resource	= heartbeat_resources,
+	.num_resources	= 1,
+	.resource	= &heartbeat_resource,
 };
 
 static struct mtd_partition nor_flash_partitions[] = {
@@ -341,8 +333,14 @@
 	pm_power_off = sh7785lcr_power_off;
 
 	/* sm501 DRAM configuration */
-	sm501_reg = (void __iomem *)0xb3e00000 + SM501_DRAM_CONTROL;
-	writel(0x000307c2, sm501_reg);
+	sm501_reg = ioremap_nocache(SM107_REG_ADDR, SM501_DRAM_CONTROL);
+	if (!sm501_reg) {
+		printk(KERN_ERR "%s: ioremap error.\n", __func__);
+		return;
+	}
+
+	writel(0x000307c2, sm501_reg + SM501_DRAM_CONTROL);
+	iounmap(sm501_reg);
 }
 
 /* Return the board specific boot mode pin configuration */
diff --git a/arch/sh/boards/board-shmin.c b/arch/sh/boards/board-shmin.c
index b1dcbbc8..325bed5 100644
--- a/arch/sh/boards/board-shmin.c
+++ b/arch/sh/boards/board-shmin.c
@@ -17,8 +17,8 @@
 
 static void __init init_shmin_irq(void)
 {
-	ctrl_outw(0x2a00, PFC_PHCR);	// IRQ0-3=IRQ
-	ctrl_outw(0x0aaa, INTC_ICR1);	// IRQ0-3=IRQ-mode,Low-active.
+	__raw_writew(0x2a00, PFC_PHCR);	// IRQ0-3=IRQ
+	__raw_writew(0x0aaa, INTC_ICR1);	// IRQ0-3=IRQ-mode,Low-active.
 	plat_irq_setup_pins(IRQ_MODE_IRQ);
 }
 
diff --git a/arch/sh/boards/board-titan.c b/arch/sh/boards/board-titan.c
new file mode 100644
index 0000000..94c36c7b
--- /dev/null
+++ b/arch/sh/boards/board-titan.c
@@ -0,0 +1,24 @@
+/*
+ * arch/sh/boards/titan/setup.c - Setup for Titan
+ *
+ *  Copyright (C) 2006  Jamie Lenehan
+ *
+ * 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/irq.h>
+#include <mach/titan.h>
+#include <asm/io.h>
+
+static void __init init_titan_irq(void)
+{
+	/* enable individual interrupt mode for externals */
+	plat_irq_setup_pins(IRQ_MODE_IRQ);
+}
+
+static struct sh_machine_vector mv_titan __initmv = {
+	.mv_name	= "Titan",
+	.mv_init_irq	= init_titan_irq,
+};
diff --git a/arch/sh/boards/board-urquell.c b/arch/sh/boards/board-urquell.c
index 36b8bac..a9bd6e3 100644
--- a/arch/sh/boards/board-urquell.c
+++ b/arch/sh/boards/board-urquell.c
@@ -2,7 +2,7 @@
  * Renesas Technology Corp. SH7786 Urquell Support.
  *
  * Copyright (C) 2008  Kuninori Morimoto <morimoto.kuninori@renesas.com>
- * Copyright (C) 2009  Paul Mundt
+ * Copyright (C) 2009, 2010  Paul Mundt
  *
  * Based on board-sh7785lcr.c
  * Copyright (C) 2008  Yoshihiro Shimoda
@@ -19,6 +19,7 @@
 #include <linux/delay.h>
 #include <linux/gpio.h>
 #include <linux/irq.h>
+#include <linux/clk.h>
 #include <mach/urquell.h>
 #include <cpu/sh7786.h>
 #include <asm/heartbeat.h>
@@ -50,26 +51,17 @@
  */
 
 /* HeartBeat */
-static struct resource heartbeat_resources[] = {
-	[0] = {
-		.start	= BOARDREG(SLEDR),
-		.end	= BOARDREG(SLEDR),
-		.flags	= IORESOURCE_MEM,
-	},
-};
-
-static struct heartbeat_data heartbeat_data = {
-	.regsize = 16,
+static struct resource heartbeat_resource = {
+	.start	= BOARDREG(SLEDR),
+	.end	= BOARDREG(SLEDR),
+	.flags	= IORESOURCE_MEM | IORESOURCE_MEM_16BIT,
 };
 
 static struct platform_device heartbeat_device = {
 	.name		= "heartbeat",
 	.id		= -1,
-	.dev	= {
-		.platform_data	= &heartbeat_data,
-	},
-	.num_resources	= ARRAY_SIZE(heartbeat_resources),
-	.resource	= heartbeat_resources,
+	.num_resources	= 1,
+	.resource	= &heartbeat_resource,
 };
 
 /* LAN91C111 */
@@ -184,6 +176,27 @@
 	return __raw_readw(UBOARDREG(MDSWMR));
 }
 
+static int urquell_clk_init(void)
+{
+	struct clk *clk;
+	int ret;
+
+	/*
+	 * Only handle the EXTAL case, anyone interfacing a crystal
+	 * resonator will need to provide their own input clock.
+	 */
+	if (test_mode_pin(MODE_PIN9))
+		return -EINVAL;
+
+	clk = clk_get(NULL, "extal");
+	if (!clk || IS_ERR(clk))
+		return PTR_ERR(clk);
+	ret = clk_set_rate(clk, 33333333);
+	clk_put(clk);
+
+	return ret;
+}
+
 /* Initialize the board */
 static void __init urquell_setup(char **cmdline_p)
 {
@@ -200,4 +213,5 @@
 	.mv_setup	= urquell_setup,
 	.mv_init_irq	= urquell_init_irq,
 	.mv_mode_pins	= urquell_mode_pins,
+	.mv_clk_init	= urquell_clk_init,
 };
diff --git a/arch/sh/boards/mach-ap325rxa/setup.c b/arch/sh/boards/mach-ap325rxa/setup.c
index 1f5fa5c..b598069 100644
--- a/arch/sh/boards/mach-ap325rxa/setup.c
+++ b/arch/sh/boards/mach-ap325rxa/setup.c
@@ -159,21 +159,21 @@
 	msleep(100);
 
 	/* ASD AP-320/325 LCD ON */
-	ctrl_outw(FPGA_LCDREG_VAL, FPGA_LCDREG);
+	__raw_writew(FPGA_LCDREG_VAL, FPGA_LCDREG);
 
 	/* backlight */
 	gpio_set_value(GPIO_PTS3, 0);
-	ctrl_outw(0x100, FPGA_BKLREG);
+	__raw_writew(0x100, FPGA_BKLREG);
 }
 
 static void ap320_wvga_power_off(void *board_data)
 {
 	/* backlight */
-	ctrl_outw(0, FPGA_BKLREG);
+	__raw_writew(0, FPGA_BKLREG);
 	gpio_set_value(GPIO_PTS3, 1);
 
 	/* ASD AP-320/325 LCD OFF */
-	ctrl_outw(0, FPGA_LCDREG);
+	__raw_writew(0, FPGA_LCDREG);
 }
 
 static struct sh_mobile_lcdc_info lcdc_info = {
@@ -420,7 +420,7 @@
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= 101,
+		.start	= 100,
 		.flags  = IORESOURCE_IRQ,
 	},
 };
@@ -443,7 +443,7 @@
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= 24,
+		.start	= 23,
 		.flags  = IORESOURCE_IRQ,
 	},
 };
@@ -595,7 +595,7 @@
 	gpio_request(GPIO_PTZ4, NULL);
 	gpio_direction_output(GPIO_PTZ4, 0); /* SADDR */
 
-	ctrl_outw(ctrl_inw(PORT_MSELCRB) & ~0x0001, PORT_MSELCRB);
+	__raw_writew(__raw_readw(PORT_MSELCRB) & ~0x0001, PORT_MSELCRB);
 
 	/* FLCTL */
 	gpio_request(GPIO_FN_FCE, NULL);
@@ -613,9 +613,9 @@
 	gpio_request(GPIO_FN_FWE, NULL);
 	gpio_request(GPIO_FN_FRB, NULL);
 
-	ctrl_outw(0, PORT_HIZCRC);
-	ctrl_outw(0xFFFF, PORT_DRVCRA);
-	ctrl_outw(0xFFFF, PORT_DRVCRB);
+	__raw_writew(0, PORT_HIZCRC);
+	__raw_writew(0xFFFF, PORT_DRVCRA);
+	__raw_writew(0xFFFF, PORT_DRVCRB);
 
 	platform_resource_setup_memory(&ceu_device, "ceu", 4 << 20);
 
diff --git a/arch/sh/boards/mach-cayman/irq.c b/arch/sh/boards/mach-cayman/irq.c
index 33f77085..1394b07 100644
--- a/arch/sh/boards/mach-cayman/irq.c
+++ b/arch/sh/boards/mach-cayman/irq.c
@@ -66,9 +66,9 @@
 	reg = EPLD_MASK_BASE + ((irq / 8) << 2);
 	bit = 1<<(irq % 8);
 	local_irq_save(flags);
-	mask = ctrl_inl(reg);
+	mask = __raw_readl(reg);
 	mask |= bit;
-	ctrl_outl(mask, reg);
+	__raw_writel(mask, reg);
 	local_irq_restore(flags);
 }
 
@@ -83,9 +83,9 @@
 	reg = EPLD_MASK_BASE + ((irq / 8) << 2);
 	bit = 1<<(irq % 8);
 	local_irq_save(flags);
-	mask = ctrl_inl(reg);
+	mask = __raw_readl(reg);
 	mask &= ~bit;
-	ctrl_outl(mask, reg);
+	__raw_writel(mask, reg);
 	local_irq_restore(flags);
 }
 
@@ -109,8 +109,8 @@
 		unsigned long status;
 		int i;
 
-		status = ctrl_inl(EPLD_STATUS_BASE) &
-			 ctrl_inl(EPLD_MASK_BASE) & 0xff;
+		status = __raw_readl(EPLD_STATUS_BASE) &
+			 __raw_readl(EPLD_MASK_BASE) & 0xff;
 		if (status == 0) {
 			irq = -1;
 		} else {
@@ -126,8 +126,8 @@
 		unsigned long status;
 		int i;
 
-		status = ctrl_inl(EPLD_STATUS_BASE + 3 * sizeof(u32)) &
-			 ctrl_inl(EPLD_MASK_BASE + 3 * sizeof(u32)) & 0xff;
+		status = __raw_readl(EPLD_STATUS_BASE + 3 * sizeof(u32)) &
+			 __raw_readl(EPLD_MASK_BASE + 3 * sizeof(u32)) & 0xff;
 		if (status == 0) {
 			irq = -1;
 		} else {
diff --git a/arch/sh/boards/mach-dreamcast/irq.c b/arch/sh/boards/mach-dreamcast/irq.c
index f55fc8e..d932667 100644
--- a/arch/sh/boards/mach-dreamcast/irq.c
+++ b/arch/sh/boards/mach-dreamcast/irq.c
@@ -135,3 +135,30 @@
 	/* Not reached */
 	return irq;
 }
+
+void systemasic_irq_init(void)
+{
+	int i, nid = cpu_to_node(boot_cpu_data);
+
+	/* Assign all virtual IRQs to the System ASIC int. handler */
+	for (i = HW_EVENT_IRQ_BASE; i < HW_EVENT_IRQ_MAX; i++) {
+		unsigned int irq;
+
+		irq = create_irq_nr(i, nid);
+		if (unlikely(irq == 0)) {
+			pr_err("%s: failed hooking irq %d for systemasic\n",
+			       __func__, i);
+			return;
+		}
+
+		if (unlikely(irq != i)) {
+			pr_err("%s: got irq %d but wanted %d, bailing.\n",
+			       __func__, irq, i);
+			destroy_irq(irq);
+			return;
+		}
+
+		set_irq_chip_and_handler(i, &systemasic_int,
+					 handle_level_irq);
+	}
+}
diff --git a/arch/sh/boards/mach-dreamcast/rtc.c b/arch/sh/boards/mach-dreamcast/rtc.c
index a743368..061d657 100644
--- a/arch/sh/boards/mach-dreamcast/rtc.c
+++ b/arch/sh/boards/mach-dreamcast/rtc.c
@@ -35,11 +35,11 @@
 	unsigned long val1, val2;
 
 	do {
-		val1 = ((ctrl_inl(AICA_RTC_SECS_H) & 0xffff) << 16) |
-			(ctrl_inl(AICA_RTC_SECS_L) & 0xffff);
+		val1 = ((__raw_readl(AICA_RTC_SECS_H) & 0xffff) << 16) |
+			(__raw_readl(AICA_RTC_SECS_L) & 0xffff);
 
-		val2 = ((ctrl_inl(AICA_RTC_SECS_H) & 0xffff) << 16) |
-			(ctrl_inl(AICA_RTC_SECS_L) & 0xffff);
+		val2 = ((__raw_readl(AICA_RTC_SECS_H) & 0xffff) << 16) |
+			(__raw_readl(AICA_RTC_SECS_L) & 0xffff);
 	} while (val1 != val2);
 
 	ts->tv_sec = val1 - TWENTY_YEARS;
@@ -60,14 +60,14 @@
 	unsigned long adj = secs + TWENTY_YEARS;
 
 	do {
-		ctrl_outl((adj & 0xffff0000) >> 16, AICA_RTC_SECS_H);
-		ctrl_outl((adj & 0xffff), AICA_RTC_SECS_L);
+		__raw_writel((adj & 0xffff0000) >> 16, AICA_RTC_SECS_H);
+		__raw_writel((adj & 0xffff), AICA_RTC_SECS_L);
 
-		val1 = ((ctrl_inl(AICA_RTC_SECS_H) & 0xffff) << 16) |
-			(ctrl_inl(AICA_RTC_SECS_L) & 0xffff);
+		val1 = ((__raw_readl(AICA_RTC_SECS_H) & 0xffff) << 16) |
+			(__raw_readl(AICA_RTC_SECS_L) & 0xffff);
 
-		val2 = ((ctrl_inl(AICA_RTC_SECS_H) & 0xffff) << 16) |
-			(ctrl_inl(AICA_RTC_SECS_L) & 0xffff);
+		val2 = ((__raw_readl(AICA_RTC_SECS_H) & 0xffff) << 16) |
+			(__raw_readl(AICA_RTC_SECS_L) & 0xffff);
 	} while (val1 != val2);
 
 	return 0;
diff --git a/arch/sh/boards/mach-dreamcast/setup.c b/arch/sh/boards/mach-dreamcast/setup.c
index a4b7402..ad1a4db 100644
--- a/arch/sh/boards/mach-dreamcast/setup.c
+++ b/arch/sh/boards/mach-dreamcast/setup.c
@@ -28,25 +28,8 @@
 #include <asm/machvec.h>
 #include <mach/sysasic.h>
 
-extern struct irq_chip systemasic_int;
-extern void aica_time_init(void);
-extern int systemasic_irq_demux(int);
-
 static void __init dreamcast_setup(char **cmdline_p)
 {
-	int i;
-
-	/* Mask all hardware events */
-	/* XXX */
-
-	/* Acknowledge any previous events */
-	/* XXX */
-
-	/* Assign all virtual IRQs to the System ASIC int. handler */
-	for (i = HW_EVENT_IRQ_BASE; i < HW_EVENT_IRQ_MAX; i++)
-		set_irq_chip_and_handler(i, &systemasic_int,
-					 handle_level_irq);
-
 	board_time_init = aica_time_init;
 }
 
@@ -54,4 +37,5 @@
 	.mv_name		= "Sega Dreamcast",
 	.mv_setup		= dreamcast_setup,
 	.mv_irq_demux		= systemasic_irq_demux,
+	.mv_init_irq		= systemasic_irq_init,
 };
diff --git a/arch/sh/boards/mach-ecovec24/sdram.S b/arch/sh/boards/mach-ecovec24/sdram.S
index 8334400..3963c6f 100644
--- a/arch/sh/boards/mach-ecovec24/sdram.S
+++ b/arch/sh/boards/mach-ecovec24/sdram.S
@@ -37,6 +37,10 @@
 	.balign 4
 ENTRY(ecovec24_sdram_leave_start)
 
+	mov.l	@(SH_SLEEP_MODE, r5), r0
+	tst	#SUSP_SH_RSTANDBY, r0
+	bf	resume_rstandby
+
 	/* DBSC: put memory in auto-refresh mode */
 
 	ED 0xFD000040, 0x00000000 /* DBRFPDN0 */
@@ -49,4 +53,59 @@
 	rts
 	 nop
 
+resume_rstandby:
+
+	/* DBSC: re-initialize and put in auto-refresh */
+
+	ED 0xFD000108, 0x00000181 /* DBPDCNT0 */
+	ED 0xFD000020, 0x015B0002 /* DBCONF */
+	ED 0xFD000030, 0x03071502 /* DBTR0 */
+	ED 0xFD000034, 0x02020102 /* DBTR1 */
+	ED 0xFD000038, 0x01090405 /* DBTR2 */
+	ED 0xFD00003C, 0x00000002 /* DBTR3 */
+	ED 0xFD000008, 0x00000005 /* DBKIND */
+	ED 0xFD000040, 0x00000001 /* DBRFPDN0 */
+	ED 0xFD000040, 0x00000000 /* DBRFPDN0 */
+	ED 0xFD000018, 0x00000001 /* DBCKECNT */
+
+	mov	#100,r0
+WAIT_400NS:
+	dt	r0
+	bf	WAIT_400NS
+
+	ED 0xFD000014, 0x00000002 /* DBCMDCNT (PALL) */
+	ED 0xFD000060, 0x00020000 /* DBMRCNT (EMR2) */
+	ED 0xFD000060, 0x00030000 /* DBMRCNT (EMR3) */
+	ED 0xFD000060, 0x00010004 /* DBMRCNT (EMR) */
+	ED 0xFD000060, 0x00000532 /* DBMRCNT (MRS) */
+	ED 0xFD000014, 0x00000002 /* DBCMDCNT (PALL) */
+	ED 0xFD000014, 0x00000004 /* DBCMDCNT (REF) */
+	ED 0xFD000014, 0x00000004 /* DBCMDCNT (REF) */
+	ED 0xFD000060, 0x00000432 /* DBMRCNT (MRS) */
+	ED 0xFD000060, 0x000103c0 /* DBMRCNT (EMR) */
+	ED 0xFD000060, 0x00010040 /* DBMRCNT (EMR) */
+
+	mov	#100,r0
+WAIT_400NS_2:
+	dt	r0
+	bf	WAIT_400NS_2
+
+	ED 0xFD000010, 0x00000001 /* DBEN */
+	ED 0xFD000044, 0x0000050f /* DBRFPDN1 */
+	ED 0xFD000048, 0x236800e6 /* DBRFPDN2 */
+
+	mov.l	DUMMY,r0
+	mov.l	@r0, r1 /* force single dummy read */
+
+	ED 0xFD000014, 0x00000002 /* DBCMDCNT (PALL) */
+	ED 0xFD000014, 0x00000004 /* DBCMDCNT (REF) */
+	ED 0xFD000108, 0x00000080 /* DBPDCNT0 */
+	ED 0xFD000040, 0x00010000 /* DBRFPDN0 */
+
+	rts
+	 nop
+
+	.balign 4
+DUMMY:	.long	0xac400000
+
 ENTRY(ecovec24_sdram_leave_end)
diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c
index 5c24628..39ed872 100644
--- a/arch/sh/boards/mach-ecovec24/setup.c
+++ b/arch/sh/boards/mach-ecovec24/setup.c
@@ -64,18 +64,16 @@
 
 /* Heartbeat */
 static unsigned char led_pos[] = { 0, 1, 2, 3 };
+
 static struct heartbeat_data heartbeat_data = {
-	.regsize = 8,
 	.nr_bits = 4,
 	.bit_pos = led_pos,
 };
 
-static struct resource heartbeat_resources[] = {
-	[0] = {
-		.start  = 0xA405012C, /* PTG */
-		.end    = 0xA405012E - 1,
-		.flags  = IORESOURCE_MEM,
-	},
+static struct resource heartbeat_resource = {
+	.start  = 0xA405012C, /* PTG */
+	.end    = 0xA405012E - 1,
+	.flags  = IORESOURCE_MEM | IORESOURCE_MEM_8BIT,
 };
 
 static struct platform_device heartbeat_device = {
@@ -84,8 +82,8 @@
 	.dev = {
 		.platform_data = &heartbeat_data,
 	},
-	.num_resources  = ARRAY_SIZE(heartbeat_resources),
-	.resource       = heartbeat_resources,
+	.num_resources  = 1,
+	.resource       = &heartbeat_resource,
 };
 
 /* MTD */
@@ -455,7 +453,7 @@
 		.flags  = IORESOURCE_MEM,
 	},
 	[1] = {
-		.start  = 101,
+		.start  = 100,
 		.flags  = IORESOURCE_IRQ,
 	},
 };
@@ -491,7 +489,7 @@
 		.flags  = IORESOURCE_MEM,
 	},
 	[1] = {
-		.start  = 24,
+		.start  = 23,
 		.flags  = IORESOURCE_IRQ,
 	},
 };
@@ -698,13 +696,13 @@
 #define FCLKBCR		0xa415000c
 static void fsimck_init(struct clk *clk)
 {
-	u32 status = ctrl_inl(clk->enable_reg);
+	u32 status = __raw_readl(clk->enable_reg);
 
 	/* use external clock */
 	status &= ~0x000000ff;
 	status |= 0x00000080;
 
-	ctrl_outl(status, clk->enable_reg);
+	__raw_writel(status, clk->enable_reg);
 }
 
 static struct clk_ops fsimck_clk_ops = {
@@ -753,6 +751,26 @@
 	},
 };
 
+/* IrDA */
+static struct resource irda_resources[] = {
+	[0] = {
+		.name	= "IrDA",
+		.start  = 0xA45D0000,
+		.end    = 0xA45D0049,
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = 20,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device irda_device = {
+	.name           = "sh_sir",
+	.num_resources  = ARRAY_SIZE(irda_resources),
+	.resource       = irda_resources,
+};
+
 static struct platform_device *ecovec_devices[] __initdata = {
 	&heartbeat_device,
 	&nor_flash_device,
@@ -773,8 +791,10 @@
 	&camera_devices[1],
 	&camera_devices[2],
 	&fsi_device,
+	&irda_device,
 };
 
+#ifdef CONFIG_I2C
 #define EEPROM_ADDR 0x50
 static u8 mac_read(struct i2c_adapter *a, u8 command)
 {
@@ -817,6 +837,12 @@
 		msleep(10);
 	}
 }
+#else
+static void __init sh_eth_init(struct sh_eth_plat_data *pd)
+{
+	pr_err("unable to read sh_eth MAC address\n");
+}
+#endif
 
 #define PORT_HIZA 0xA4050158
 #define IODRIVEA  0xA405018A
@@ -831,7 +857,8 @@
 	struct clk *clk;
 
 	/* register board specific self-refresh code */
-	sh_mobile_register_self_refresh(SUSP_SH_STANDBY | SUSP_SH_SF,
+	sh_mobile_register_self_refresh(SUSP_SH_STANDBY | SUSP_SH_SF |
+					SUSP_SH_RSTANDBY,
 					&ecovec24_sdram_enter_start,
 					&ecovec24_sdram_enter_end,
 					&ecovec24_sdram_leave_start,
@@ -855,7 +882,7 @@
 	gpio_direction_output(GPIO_PTG1, 0);
 	gpio_direction_output(GPIO_PTG2, 0);
 	gpio_direction_output(GPIO_PTG3, 0);
-	ctrl_outw((ctrl_inw(PORT_HIZA) & ~(0x1 << 1)) , PORT_HIZA);
+	__raw_writew((__raw_readw(PORT_HIZA) & ~(0x1 << 1)) , PORT_HIZA);
 
 	/* enable SH-Eth */
 	gpio_request(GPIO_PTA1, NULL);
@@ -875,16 +902,16 @@
 	gpio_request(GPIO_FN_LNKSTA,       NULL);
 
 	/* enable USB */
-	ctrl_outw(0x0000, 0xA4D80000);
-	ctrl_outw(0x0000, 0xA4D90000);
+	__raw_writew(0x0000, 0xA4D80000);
+	__raw_writew(0x0000, 0xA4D90000);
 	gpio_request(GPIO_PTB3,  NULL);
 	gpio_request(GPIO_PTB4,  NULL);
 	gpio_request(GPIO_PTB5,  NULL);
 	gpio_direction_input(GPIO_PTB3);
 	gpio_direction_output(GPIO_PTB4, 0);
 	gpio_direction_output(GPIO_PTB5, 0);
-	ctrl_outw(0x0600, 0xa40501d4);
-	ctrl_outw(0x0600, 0xa4050192);
+	__raw_writew(0x0600, 0xa40501d4);
+	__raw_writew(0x0600, 0xa4050192);
 
 	if (gpio_get_value(GPIO_PTB3)) {
 		printk(KERN_INFO "USB1 function is selected\n");
@@ -925,7 +952,7 @@
 	gpio_request(GPIO_FN_LCDVSYN,  NULL);
 	gpio_request(GPIO_FN_LCDDON,   NULL);
 	gpio_request(GPIO_FN_LCDLCLK,  NULL);
-	ctrl_outw((ctrl_inw(PORT_HIZA) & ~0x0001), PORT_HIZA);
+	__raw_writew((__raw_readw(PORT_HIZA) & ~0x0001), PORT_HIZA);
 
 	gpio_request(GPIO_PTE6, NULL);
 	gpio_request(GPIO_PTU1, NULL);
@@ -937,7 +964,7 @@
 	gpio_direction_output(GPIO_PTA2, 0);
 
 	/* I/O buffer drive ability is high */
-	ctrl_outw((ctrl_inw(IODRIVEA) & ~0x00c0) | 0x0080 , IODRIVEA);
+	__raw_writew((__raw_readw(IODRIVEA) & ~0x00c0) | 0x0080 , IODRIVEA);
 
 	if (gpio_get_value(GPIO_PTE6)) {
 		/* DVI */
@@ -1069,7 +1096,7 @@
 	gpio_direction_output(GPIO_PTB7, 0);
 
 	/* I/O buffer drive ability is high for SDHI1 */
-	ctrl_outw((ctrl_inw(IODRIVEA) & ~0x3000) | 0x2000 , IODRIVEA);
+	__raw_writew((__raw_readw(IODRIVEA) & ~0x3000) | 0x2000 , IODRIVEA);
 #else
 	/* enable MSIOF0 on CN11 (needs DS2.4 set to OFF) */
 	gpio_request(GPIO_FN_MSIOF0_TXD, NULL);
@@ -1107,6 +1134,11 @@
 	gpio_request(GPIO_FN_FSIOBLRCK,  NULL);
 	gpio_request(GPIO_FN_CLKAUDIOBO, NULL);
 
+	/* set SPU2 clock to 83.4 MHz */
+	clk = clk_get(NULL, "spu_clk");
+	clk_set_rate(clk, clk_round_rate(clk, 83333333));
+	clk_put(clk);
+
 	/* change parent of FSI B */
 	clk = clk_get(NULL, "fsib_clk");
 	clk_register(&fsimckb_clk);
@@ -1123,6 +1155,17 @@
 	gpio_request(GPIO_FN_INTC_IRQ1, NULL);
 	gpio_direction_input(GPIO_FN_INTC_IRQ1);
 
+	/* set VPU clock to 166 MHz */
+	clk = clk_get(NULL, "vpu_clk");
+	clk_set_rate(clk, clk_round_rate(clk, 166000000));
+	clk_put(clk);
+
+	/* enable IrDA */
+	gpio_request(GPIO_FN_IRDA_OUT, NULL);
+	gpio_request(GPIO_FN_IRDA_IN,  NULL);
+	gpio_request(GPIO_PTU5, NULL);
+	gpio_direction_output(GPIO_PTU5, 0);
+
 	/* enable I2C device */
 	i2c_register_board_info(0, i2c0_devices,
 				ARRAY_SIZE(i2c0_devices));
diff --git a/arch/sh/boards/mach-highlander/irq-r7780mp.c b/arch/sh/boards/mach-highlander/irq-r7780mp.c
index 83c28bc..9893fd3 100644
--- a/arch/sh/boards/mach-highlander/irq-r7780mp.c
+++ b/arch/sh/boards/mach-highlander/irq-r7780mp.c
@@ -64,7 +64,7 @@
 
 unsigned char * __init highlander_plat_irq_setup(void)
 {
-	if ((ctrl_inw(0xa4000700) & 0xf000) == 0x2000) {
+	if ((__raw_readw(0xa4000700) & 0xf000) == 0x2000) {
 		printk(KERN_INFO "Using r7780mp interrupt controller.\n");
 		register_intc_controller(&intc_desc);
 		return irl2irq;
diff --git a/arch/sh/boards/mach-highlander/irq-r7780rp.c b/arch/sh/boards/mach-highlander/irq-r7780rp.c
index b721e86..0805b21 100644
--- a/arch/sh/boards/mach-highlander/irq-r7780rp.c
+++ b/arch/sh/boards/mach-highlander/irq-r7780rp.c
@@ -57,7 +57,7 @@
 
 unsigned char * __init highlander_plat_irq_setup(void)
 {
-	if (ctrl_inw(0xa5000600)) {
+	if (__raw_readw(0xa5000600)) {
 		printk(KERN_INFO "Using r7780rp interrupt controller.\n");
 		register_intc_controller(&intc_desc);
 		return irl2irq;
diff --git a/arch/sh/boards/mach-highlander/irq-r7785rp.c b/arch/sh/boards/mach-highlander/irq-r7785rp.c
index 3811b06..558b248 100644
--- a/arch/sh/boards/mach-highlander/irq-r7785rp.c
+++ b/arch/sh/boards/mach-highlander/irq-r7785rp.c
@@ -66,20 +66,20 @@
 
 unsigned char * __init highlander_plat_irq_setup(void)
 {
-	if ((ctrl_inw(0xa4000158) & 0xf000) != 0x1000)
+	if ((__raw_readw(0xa4000158) & 0xf000) != 0x1000)
 		return NULL;
 
 	printk(KERN_INFO "Using r7785rp interrupt controller.\n");
 
-	ctrl_outw(0x0000, PA_IRLSSR1);	/* FPGA IRLSSR1(CF_CD clear) */
+	__raw_writew(0x0000, PA_IRLSSR1);	/* FPGA IRLSSR1(CF_CD clear) */
 
 	/* Setup the FPGA IRL */
-	ctrl_outw(0x0000, PA_IRLPRA);	/* FPGA IRLA */
-	ctrl_outw(0xe598, PA_IRLPRB);	/* FPGA IRLB */
-	ctrl_outw(0x7060, PA_IRLPRC);	/* FPGA IRLC */
-	ctrl_outw(0x0000, PA_IRLPRD);	/* FPGA IRLD */
-	ctrl_outw(0x4321, PA_IRLPRE);	/* FPGA IRLE */
-	ctrl_outw(0xdcba, PA_IRLPRF);	/* FPGA IRLF */
+	__raw_writew(0x0000, PA_IRLPRA);	/* FPGA IRLA */
+	__raw_writew(0xe598, PA_IRLPRB);	/* FPGA IRLB */
+	__raw_writew(0x7060, PA_IRLPRC);	/* FPGA IRLC */
+	__raw_writew(0x0000, PA_IRLPRD);	/* FPGA IRLD */
+	__raw_writew(0x4321, PA_IRLPRE);	/* FPGA IRLE */
+	__raw_writew(0xdcba, PA_IRLPRF);	/* FPGA IRLF */
 
 	register_intc_controller(&intc_desc);
 	return irl2irq;
diff --git a/arch/sh/boards/mach-highlander/psw.c b/arch/sh/boards/mach-highlander/psw.c
index 37b1a2e..5227863 100644
--- a/arch/sh/boards/mach-highlander/psw.c
+++ b/arch/sh/boards/mach-highlander/psw.c
@@ -24,7 +24,7 @@
 	unsigned int l, mask;
 	int ret = 0;
 
-	l = ctrl_inw(PA_DBSW);
+	l = __raw_readw(PA_DBSW);
 
 	/* Nothing to do if there's no state change */
 	if (psw->state) {
@@ -45,7 +45,7 @@
 out:
 	/* Clear the switch IRQs */
 	l |= (0x7 << 12);
-	ctrl_outw(l, PA_DBSW);
+	__raw_writew(l, PA_DBSW);
 
 	return IRQ_RETVAL(ret);
 }
diff --git a/arch/sh/boards/mach-highlander/setup.c b/arch/sh/boards/mach-highlander/setup.c
index f663c14..affd667 100644
--- a/arch/sh/boards/mach-highlander/setup.c
+++ b/arch/sh/boards/mach-highlander/setup.c
@@ -311,13 +311,13 @@
  */
 static int ivdr_clk_enable(struct clk *clk)
 {
-	ctrl_outw(ctrl_inw(PA_IVDRCTL) | (1 << IVDR_CK_ON), PA_IVDRCTL);
+	__raw_writew(__raw_readw(PA_IVDRCTL) | (1 << IVDR_CK_ON), PA_IVDRCTL);
 	return 0;
 }
 
 static void ivdr_clk_disable(struct clk *clk)
 {
-	ctrl_outw(ctrl_inw(PA_IVDRCTL) & ~(1 << IVDR_CK_ON), PA_IVDRCTL);
+	__raw_writew(__raw_readw(PA_IVDRCTL) & ~(1 << IVDR_CK_ON), PA_IVDRCTL);
 }
 
 static struct clk_ops ivdr_clk_ops = {
@@ -337,7 +337,7 @@
 static void r7780rp_power_off(void)
 {
 	if (mach_is_r7780mp() || mach_is_r7785rp())
-		ctrl_outw(0x0001, PA_POFF);
+		__raw_writew(0x0001, PA_POFF);
 }
 
 /*
@@ -345,7 +345,7 @@
  */
 static void __init highlander_setup(char **cmdline_p)
 {
-	u16 ver = ctrl_inw(PA_VERREG);
+	u16 ver = __raw_readw(PA_VERREG);
 	int i;
 
 	printk(KERN_INFO "Renesas Solutions Highlander %s support.\n",
@@ -370,12 +370,12 @@
 		clk_enable(clk);
 	}
 
-	ctrl_outw(0x0000, PA_OBLED);	/* Clear LED. */
+	__raw_writew(0x0000, PA_OBLED);	/* Clear LED. */
 
 	if (mach_is_r7780rp())
-		ctrl_outw(0x0001, PA_SDPOW);	/* SD Power ON */
+		__raw_writew(0x0001, PA_SDPOW);	/* SD Power ON */
 
-	ctrl_outw(ctrl_inw(PA_IVDRCTL) | 0x01, PA_IVDRCTL);	/* Si13112 */
+	__raw_writew(__raw_readw(PA_IVDRCTL) | 0x01, PA_IVDRCTL);	/* Si13112 */
 
 	pm_power_off = r7780rp_power_off;
 }
diff --git a/arch/sh/boards/mach-hp6xx/hp6xx_apm.c b/arch/sh/boards/mach-hp6xx/hp6xx_apm.c
index e85212f..b49535c 100644
--- a/arch/sh/boards/mach-hp6xx/hp6xx_apm.c
+++ b/arch/sh/boards/mach-hp6xx/hp6xx_apm.c
@@ -53,7 +53,7 @@
 	info->ac_line_status = (battery > HP680_BATTERY_AC_ON) ?
 			 APM_AC_ONLINE : APM_AC_OFFLINE;
 
-	pgdr = ctrl_inb(PGDR);
+	pgdr = __raw_readb(PGDR);
 	if (pgdr & PGDR_MAIN_BATTERY_OUT) {
 		info->battery_status	= APM_BATTERY_STATUS_NOT_PRESENT;
 		info->battery_flag	= 0x80;
diff --git a/arch/sh/boards/mach-hp6xx/pm.c b/arch/sh/boards/mach-hp6xx/pm.c
index d936c1a..4499a37 100644
--- a/arch/sh/boards/mach-hp6xx/pm.c
+++ b/arch/sh/boards/mach-hp6xx/pm.c
@@ -53,17 +53,17 @@
 	sh_wdt_write_cnt(0);
 
 	/* disable PLL1 */
-	frqcr = ctrl_inw(FRQCR);
+	frqcr = __raw_readw(FRQCR);
 	frqcr &= ~(FRQCR_PLLEN | FRQCR_PSTBY);
-	ctrl_outw(frqcr, FRQCR);
+	__raw_writew(frqcr, FRQCR);
 
 	/* enable standby */
-	stbcr = ctrl_inb(STBCR);
-	ctrl_outb(stbcr | STBCR_STBY | STBCR_MSTP2, STBCR);
+	stbcr = __raw_readb(STBCR);
+	__raw_writeb(stbcr | STBCR_STBY | STBCR_MSTP2, STBCR);
 
 	/* set self-refresh */
-	mcr = ctrl_inw(MCR);
-	ctrl_outw(mcr & ~MCR_RFSH, MCR);
+	mcr = __raw_readw(MCR);
+	__raw_writew(mcr & ~MCR_RFSH, MCR);
 
 	/* set interrupt handler */
 	asm volatile("stc vbr, %0" : "=r" (vbr_old));
@@ -73,8 +73,8 @@
 	       &wakeup_start, &wakeup_end - &wakeup_start);
 	asm volatile("ldc %0, vbr" : : "r" (vbr_new));
 
-	ctrl_outw(0, RTCNT);
-	ctrl_outw(mcr | MCR_RFSH | MCR_RMODE, MCR);
+	__raw_writew(0, RTCNT);
+	__raw_writew(mcr | MCR_RFSH | MCR_RMODE, MCR);
 
 	cpu_sleep();
 
@@ -83,14 +83,14 @@
 	free_page(vbr_new);
 
 	/* enable PLL1 */
-	frqcr = ctrl_inw(FRQCR);
+	frqcr = __raw_readw(FRQCR);
 	frqcr |= FRQCR_PSTBY;
-	ctrl_outw(frqcr, FRQCR);
+	__raw_writew(frqcr, FRQCR);
 	udelay(50);
 	frqcr |= FRQCR_PLLEN;
-	ctrl_outw(frqcr, FRQCR);
+	__raw_writew(frqcr, FRQCR);
 
-	ctrl_outb(stbcr, STBCR);
+	__raw_writeb(stbcr, STBCR);
 
 	clear_bl_bit();
 }
@@ -115,21 +115,21 @@
 	outw(hd64461_stbcr, HD64461_STBCR);
 #endif
 
-	ctrl_outb(0x1f, DACR);
+	__raw_writeb(0x1f, DACR);
 
-	stbcr = ctrl_inb(STBCR);
-	ctrl_outb(0x01, STBCR);
+	stbcr = __raw_readb(STBCR);
+	__raw_writeb(0x01, STBCR);
 
-	stbcr2 = ctrl_inb(STBCR2);
-	ctrl_outb(0x7f , STBCR2);
+	stbcr2 = __raw_readb(STBCR2);
+	__raw_writeb(0x7f , STBCR2);
 
 	outw(0xf07f, HD64461_SCPUCR);
 
 	pm_enter();
 
 	outw(0, HD64461_SCPUCR);
-	ctrl_outb(stbcr, STBCR);
-	ctrl_outb(stbcr2, STBCR2);
+	__raw_writeb(stbcr, STBCR);
+	__raw_writeb(stbcr2, STBCR2);
 
 #ifdef CONFIG_HD64461_ENABLER
 	hd64461_stbcr = inw(HD64461_STBCR);
diff --git a/arch/sh/boards/mach-hp6xx/setup.c b/arch/sh/boards/mach-hp6xx/setup.c
index e6dd5e9..8c9add5 100644
--- a/arch/sh/boards/mach-hp6xx/setup.c
+++ b/arch/sh/boards/mach-hp6xx/setup.c
@@ -149,19 +149,19 @@
 
 	sh_dac_output(0, DAC_SPEAKER_VOLUME);
 	sh_dac_disable(DAC_SPEAKER_VOLUME);
-	v8 = ctrl_inb(DACR);
+	v8 = __raw_readb(DACR);
 	v8 &= ~DACR_DAE;
-	ctrl_outb(v8,DACR);
+	__raw_writeb(v8,DACR);
 
-	v8 = ctrl_inb(SCPDR);
+	v8 = __raw_readb(SCPDR);
 	v8 |= SCPDR_TS_SCAN_X | SCPDR_TS_SCAN_Y;
 	v8 &= ~SCPDR_TS_SCAN_ENABLE;
-	ctrl_outb(v8, SCPDR);
+	__raw_writeb(v8, SCPDR);
 
-	v = ctrl_inw(SCPCR);
+	v = __raw_readw(SCPCR);
 	v &= ~SCPCR_TS_MASK;
 	v |= SCPCR_TS_ENABLE;
-	ctrl_outw(v, SCPCR);
+	__raw_writew(v, SCPCR);
 }
 device_initcall(hp6xx_devices_setup);
 
diff --git a/arch/sh/boards/mach-kfr2r09/setup.c b/arch/sh/boards/mach-kfr2r09/setup.c
index 5d7b5d9..b2cd0ed 100644
--- a/arch/sh/boards/mach-kfr2r09/setup.c
+++ b/arch/sh/boards/mach-kfr2r09/setup.c
@@ -282,7 +282,7 @@
 		 * use 1.8 V for VccQ_VIO
 		 * use 2.85V for VccQ_SR
 		 */
-		ctrl_outw((ctrl_inw(DRVCRB) & ~0x0003) | 0x0001, DRVCRB);
+		__raw_writew((__raw_readw(DRVCRB) & ~0x0003) | 0x0001, DRVCRB);
 
 		/* reset clear */
 		ret = gpio_request(GPIO_PTB4, NULL);
@@ -351,7 +351,7 @@
 		.flags  = IORESOURCE_MEM,
 	},
 	[1] = {
-		.start  = 101,
+		.start  = 100,
 		.flags  = IORESOURCE_IRQ,
 	},
 };
@@ -492,13 +492,13 @@
 	if (kfr2r09_usb0_gadget_i2c_setup() != 0)
 		return -ENODEV; /* unable to configure using i2c */
 
-	ctrl_outw((ctrl_inw(PORT_MSELCRB) & ~0xc000) | 0x8000, PORT_MSELCRB);
+	__raw_writew((__raw_readw(PORT_MSELCRB) & ~0xc000) | 0x8000, PORT_MSELCRB);
 	gpio_request(GPIO_FN_PDSTATUS, NULL); /* R-standby disables USB clock */
 	gpio_request(GPIO_PTV6, NULL); /* USBCLK_ON */
 	gpio_direction_output(GPIO_PTV6, 1); /* USBCLK_ON = H */
 	msleep(20); /* wait 20ms to let the clock settle */
 	clk_enable(clk_get(NULL, "usb0"));
-	ctrl_outw(0x0600, 0xa40501d4);
+	__raw_writew(0x0600, 0xa40501d4);
 
 	return 0;
 }
@@ -526,12 +526,12 @@
 	gpio_direction_output(GPIO_PTG3, 1); /* HPON_ON = H */
 
 	/* setup NOR flash at CS0 */
-	ctrl_outl(0x36db0400, BSC_CS0BCR);
-	ctrl_outl(0x00000500, BSC_CS0WCR);
+	__raw_writel(0x36db0400, BSC_CS0BCR);
+	__raw_writel(0x00000500, BSC_CS0WCR);
 
 	/* setup NAND flash at CS4 */
-	ctrl_outl(0x36db0400, BSC_CS4BCR);
-	ctrl_outl(0x00000500, BSC_CS4WCR);
+	__raw_writel(0x36db0400, BSC_CS4BCR);
+	__raw_writel(0x00000500, BSC_CS4WCR);
 
 	/* setup KEYSC pins */
 	gpio_request(GPIO_FN_KEYOUT0, NULL);
diff --git a/arch/sh/boards/mach-landisk/gio.c b/arch/sh/boards/mach-landisk/gio.c
index 5280131..01e6abb 100644
--- a/arch/sh/boards/mach-landisk/gio.c
+++ b/arch/sh/boards/mach-landisk/gio.c
@@ -76,39 +76,39 @@
 		break;
 
 	case GIODRV_IOCSGIODATA1:	/* write byte */
-		ctrl_outb((unsigned char)(0x0ff & data), addr);
+		__raw_writeb((unsigned char)(0x0ff & data), addr);
 		break;
 
 	case GIODRV_IOCSGIODATA2:	/* write word */
 		if (addr & 0x01) {
 			return -EFAULT;
 		}
-		ctrl_outw((unsigned short int)(0x0ffff & data), addr);
+		__raw_writew((unsigned short int)(0x0ffff & data), addr);
 		break;
 
 	case GIODRV_IOCSGIODATA4:	/* write long */
 		if (addr & 0x03) {
 			return -EFAULT;
 		}
-		ctrl_outl(data, addr);
+		__raw_writel(data, addr);
 		break;
 
 	case GIODRV_IOCGGIODATA1:	/* read byte */
-		data = ctrl_inb(addr);
+		data = __raw_readb(addr);
 		break;
 
 	case GIODRV_IOCGGIODATA2:	/* read word */
 		if (addr & 0x01) {
 			return -EFAULT;
 		}
-		data = ctrl_inw(addr);
+		data = __raw_readw(addr);
 		break;
 
 	case GIODRV_IOCGGIODATA4:	/* read long */
 		if (addr & 0x03) {
 			return -EFAULT;
 		}
-		data = ctrl_inl(addr);
+		data = __raw_readl(addr);
 		break;
 	default:
 		return -EFAULT;
diff --git a/arch/sh/boards/mach-landisk/irq.c b/arch/sh/boards/mach-landisk/irq.c
index 7b284cd..96f38a4 100644
--- a/arch/sh/boards/mach-landisk/irq.c
+++ b/arch/sh/boards/mach-landisk/irq.c
@@ -22,14 +22,14 @@
 {
 	unsigned char mask = 0xff ^ (0x01 << (irq - 5));
 
-	ctrl_outb(ctrl_inb(PA_IMASK) & mask, PA_IMASK);
+	__raw_writeb(__raw_readb(PA_IMASK) & mask, PA_IMASK);
 }
 
 static void enable_landisk_irq(unsigned int irq)
 {
 	unsigned char value = (0x01 << (irq - 5));
 
-	ctrl_outb(ctrl_inb(PA_IMASK) | value, PA_IMASK);
+	__raw_writeb(__raw_readb(PA_IMASK) | value, PA_IMASK);
 }
 
 static struct irq_chip landisk_irq_chip __read_mostly = {
@@ -52,5 +52,5 @@
 					      handle_level_irq, "level");
 		enable_landisk_irq(i);
 	}
-	ctrl_outb(0x00, PA_PWRINT_CLR);
+	__raw_writeb(0x00, PA_PWRINT_CLR);
 }
diff --git a/arch/sh/boards/mach-landisk/psw.c b/arch/sh/boards/mach-landisk/psw.c
index e6b0efa..bef8352 100644
--- a/arch/sh/boards/mach-landisk/psw.c
+++ b/arch/sh/boards/mach-landisk/psw.c
@@ -25,7 +25,7 @@
 	unsigned int sw_value;
 	int ret = 0;
 
-	sw_value = (0x0ff & (~ctrl_inb(PA_STATUS)));
+	sw_value = (0x0ff & (~__raw_readb(PA_STATUS)));
 
 	/* Nothing to do if there's no state change */
 	if (psw->state) {
@@ -42,7 +42,7 @@
 
 out:
 	/* Clear the switch IRQs */
-	ctrl_outb(0x00, PA_PWRINT_CLR);
+	__raw_writeb(0x00, PA_PWRINT_CLR);
 
 	return IRQ_RETVAL(ret);
 }
diff --git a/arch/sh/boards/mach-landisk/setup.c b/arch/sh/boards/mach-landisk/setup.c
index db22ea2..50337acc 100644
--- a/arch/sh/boards/mach-landisk/setup.c
+++ b/arch/sh/boards/mach-landisk/setup.c
@@ -25,7 +25,7 @@
 
 static void landisk_power_off(void)
 {
-        ctrl_outb(0x01, PA_SHUTDOWN);
+        __raw_writeb(0x01, PA_SHUTDOWN);
 }
 
 static struct resource cf_ide_resources[3];
@@ -63,7 +63,7 @@
 	/* open I/O area window */
 	paddrbase = virt_to_phys((void *)PA_AREA5_IO);
 	prot = PAGE_KERNEL_PCC(1, _PAGE_PCC_IO16);
-	cf_ide_base = p3_ioremap(paddrbase, PAGE_SIZE, prot.pgprot);
+	cf_ide_base = ioremap_prot(paddrbase, PAGE_SIZE, pgprot_val(prot));
 	if (!cf_ide_base) {
 		printk("allocate_cf_area : can't open CF I/O window!\n");
 		return -ENOMEM;
@@ -88,7 +88,7 @@
 static void __init landisk_setup(char **cmdline_p)
 {
         /* LED ON */
-	ctrl_outb(ctrl_inb(PA_LED) | 0x03, PA_LED);
+	__raw_writeb(__raw_readb(PA_LED) | 0x03, PA_LED);
 
 	printk(KERN_INFO "I-O DATA DEVICE, INC. \"LANDISK Series\" support.\n");
 	pm_power_off = landisk_power_off;
diff --git a/arch/sh/boards/mach-lboxre2/setup.c b/arch/sh/boards/mach-lboxre2/setup.c
index 2b0b581..79b4e0d7 100644
--- a/arch/sh/boards/mach-lboxre2/setup.c
+++ b/arch/sh/boards/mach-lboxre2/setup.c
@@ -56,8 +56,8 @@
 	/* open I/O area window */
 	paddrbase = virt_to_phys((void*)PA_AREA5_IO);
 	psize = PAGE_SIZE;
-	prot = PAGE_KERNEL_PCC( 1 , _PAGE_PCC_IO16);
-	cf0_io_base = (u32)p3_ioremap(paddrbase, psize, prot.pgprot);
+	prot = PAGE_KERNEL_PCC(1, _PAGE_PCC_IO16);
+	cf0_io_base = (u32)ioremap_prot(paddrbase, psize, pgprot_val(prot));
 	if (!cf0_io_base) {
 		printk(KERN_ERR "%s : can't open CF I/O window!\n" , __func__ );
 		return -ENOMEM;
diff --git a/arch/sh/boards/mach-microdev/io.c b/arch/sh/boards/mach-microdev/io.c
index 52dd748..2960c65 100644
--- a/arch/sh/boards/mach-microdev/io.c
+++ b/arch/sh/boards/mach-microdev/io.c
@@ -141,10 +141,10 @@
 #if defined(CONFIG_PCI)
 	/* System board present, just make a dummy SRAM access.  (CS0 will be
 	   mapped to PCI memory, probably good to avoid it.) */
-	ctrl_inw(0xa6800000);
+	__raw_readw(0xa6800000);
 #else
 	/* CS0 will be mapped to flash, ROM etc so safe to access it. */
-	ctrl_inw(0xa0000000);
+	__raw_readw(0xa0000000);
 #endif
 }
 
diff --git a/arch/sh/boards/mach-microdev/irq.c b/arch/sh/boards/mach-microdev/irq.c
index b551963..a26d166 100644
--- a/arch/sh/boards/mach-microdev/irq.c
+++ b/arch/sh/boards/mach-microdev/irq.c
@@ -88,7 +88,7 @@
 	fpgaIrq = fpgaIrqTable[irq].fpgaIrq;
 
 	/* disable interrupts on the FPGA INTC register */
-	ctrl_outl(MICRODEV_FPGA_INTC_MASK(fpgaIrq), MICRODEV_FPGA_INTDSB_REG);
+	__raw_writel(MICRODEV_FPGA_INTC_MASK(fpgaIrq), MICRODEV_FPGA_INTDSB_REG);
 }
 
 static void enable_microdev_irq(unsigned int irq)
@@ -107,13 +107,13 @@
 	priorityReg = MICRODEV_FPGA_INTPRI_REG(fpgaIrq);
 
 	/* set priority for the interrupt */
-	priorities = ctrl_inl(priorityReg);
+	priorities = __raw_readl(priorityReg);
 	priorities &= ~MICRODEV_FPGA_INTPRI_MASK(fpgaIrq);
 	priorities |= MICRODEV_FPGA_INTPRI_LEVEL(fpgaIrq, pri);
-	ctrl_outl(priorities, priorityReg);
+	__raw_writel(priorities, priorityReg);
 
 	/* enable interrupts on the FPGA INTC register */
-	ctrl_outl(MICRODEV_FPGA_INTC_MASK(fpgaIrq), MICRODEV_FPGA_INTENB_REG);
+	__raw_writel(MICRODEV_FPGA_INTC_MASK(fpgaIrq), MICRODEV_FPGA_INTENB_REG);
 }
 
 /* This function sets the desired irq handler to be a MicroDev type */
@@ -134,7 +134,7 @@
 	int i;
 
 	/* disable interrupts on the FPGA INTC register */
-	ctrl_outl(~0ul, MICRODEV_FPGA_INTDSB_REG);
+	__raw_writel(~0ul, MICRODEV_FPGA_INTDSB_REG);
 
 	for (i = 0; i < NUM_EXTERNAL_IRQS; i++)
 		make_microdev_irq(i);
diff --git a/arch/sh/boards/mach-migor/setup.c b/arch/sh/boards/mach-migor/setup.c
index 507c77b..e08d513 100644
--- a/arch/sh/boards/mach-migor/setup.c
+++ b/arch/sh/boards/mach-migor/setup.c
@@ -397,7 +397,7 @@
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= 101,
+		.start	= 100,
 		.flags  = IORESOURCE_IRQ,
 	},
 };
@@ -496,28 +496,16 @@
 					&migor_sdram_enter_end,
 					&migor_sdram_leave_start,
 					&migor_sdram_leave_end);
-#ifdef CONFIG_PM
 	/* Let D11 LED show STATUS0 */
 	gpio_request(GPIO_FN_STATUS0, NULL);
 
 	/* Lit D12 LED show PDSTATUS */
 	gpio_request(GPIO_FN_PDSTATUS, NULL);
-#else
-	/* Lit D11 LED */
-	gpio_request(GPIO_PTJ7, NULL);
-	gpio_direction_output(GPIO_PTJ7, 1);
-	gpio_export(GPIO_PTJ7, 0);
-
-	/* Lit D12 LED */
-	gpio_request(GPIO_PTJ5, NULL);
-	gpio_direction_output(GPIO_PTJ5, 1);
-	gpio_export(GPIO_PTJ5, 0);
-#endif
 
 	/* SMC91C111 - Enable IRQ0, Setup CS4 for 16-bit fast access */
 	gpio_request(GPIO_FN_IRQ0, NULL);
-	ctrl_outl(0x00003400, BSC_CS4BCR);
-	ctrl_outl(0x00110080, BSC_CS4WCR);
+	__raw_writel(0x00003400, BSC_CS4BCR);
+	__raw_writel(0x00110080, BSC_CS4WCR);
 
 	/* KEYSC */
 	gpio_request(GPIO_FN_KEYOUT0, NULL);
@@ -533,7 +521,7 @@
 
 	/* NAND Flash */
 	gpio_request(GPIO_FN_CS6A_CE2B, NULL);
-	ctrl_outl((ctrl_inl(BSC_CS6ABCR) & ~0x0600) | 0x0200, BSC_CS6ABCR);
+	__raw_writel((__raw_readl(BSC_CS6ABCR) & ~0x0600) | 0x0200, BSC_CS6ABCR);
 	gpio_request(GPIO_PTA1, NULL);
 	gpio_direction_input(GPIO_PTA1);
 
@@ -627,7 +615,7 @@
 #else
 	gpio_direction_output(GPIO_PTT0, 1);
 #endif
-	ctrl_outw(ctrl_inw(PORT_MSELCRB) | 0x2000, PORT_MSELCRB); /* D15->D8 */
+	__raw_writew(__raw_readw(PORT_MSELCRB) | 0x2000, PORT_MSELCRB); /* D15->D8 */
 
 	platform_resource_setup_memory(&migor_ceu_device, "ceu", 4 << 20);
 
diff --git a/arch/sh/boards/mach-r2d/irq.c b/arch/sh/boards/mach-r2d/irq.c
index 78d7b27..574f009 100644
--- a/arch/sh/boards/mach-r2d/irq.c
+++ b/arch/sh/boards/mach-r2d/irq.c
@@ -129,7 +129,7 @@
 {
 	struct intc_desc *d;
 
-	switch (ctrl_inw(PA_VERREG) & 0xf0) {
+	switch (__raw_readw(PA_VERREG) & 0xf0) {
 #ifdef CONFIG_RTS7751R2D_PLUS
 	case 0x10:
 		printk(KERN_INFO "Using R2D-PLUS interrupt controller.\n");
@@ -147,7 +147,7 @@
 #endif
 	default:
 		printk(KERN_INFO "Unknown R2D interrupt controller 0x%04x\n",
-		       ctrl_inw(PA_VERREG));
+		       __raw_readw(PA_VERREG));
 		return;
 	}
 
diff --git a/arch/sh/boards/mach-r2d/setup.c b/arch/sh/boards/mach-r2d/setup.c
index a625ecb..b84df6a 100644
--- a/arch/sh/boards/mach-r2d/setup.c
+++ b/arch/sh/boards/mach-r2d/setup.c
@@ -70,7 +70,7 @@
 static void r2d_chip_select(struct sh_spi_info *spi, int cs, int state)
 {
 	BUG_ON(cs != 0);  /* Single Epson RTC-9701JE attached on CS0 */
-	ctrl_outw(state == BITBANG_CS_ACTIVE, PA_RTCCE);
+	__raw_writew(state == BITBANG_CS_ACTIVE, PA_RTCCE);
 }
 
 static struct sh_spi_info spi_info = {
@@ -262,7 +262,7 @@
 
 static void rts7751r2d_power_off(void)
 {
-	ctrl_outw(0x0001, PA_POWOFF);
+	__raw_writew(0x0001, PA_POWOFF);
 }
 
 /*
@@ -271,14 +271,14 @@
 static void __init rts7751r2d_setup(char **cmdline_p)
 {
 	void __iomem *sm501_reg;
-	u16 ver = ctrl_inw(PA_VERREG);
+	u16 ver = __raw_readw(PA_VERREG);
 
 	printk(KERN_INFO "Renesas Technology Sales RTS7751R2D support.\n");
 
 	printk(KERN_INFO "FPGA version:%d (revision:%d)\n",
 					(ver >> 4) & 0xf, ver & 0xf);
 
-	ctrl_outw(0x0000, PA_OUTPORT);
+	__raw_writew(0x0000, PA_OUTPORT);
 	pm_power_off = rts7751r2d_power_off;
 
 	/* sm501 dram configuration:
diff --git a/arch/sh/boards/mach-rsk/devices-rsk7203.c b/arch/sh/boards/mach-rsk/devices-rsk7203.c
index c37617e..4fa08ba 100644
--- a/arch/sh/boards/mach-rsk/devices-rsk7203.c
+++ b/arch/sh/boards/mach-rsk/devices-rsk7203.c
@@ -96,7 +96,7 @@
 	gpio_request(GPIO_FN_RXD0, NULL);
 
 	/* Setup LAN9118: CS1 in 16-bit Big Endian Mode, IRQ0 at Port B */
-	ctrl_outl(0x36db0400, 0xfffc0008); /* CS1BCR */
+	__raw_writel(0x36db0400, 0xfffc0008); /* CS1BCR */
 	gpio_request(GPIO_FN_IRQ0_PB, NULL);
 
 	return platform_add_devices(rsk7203_devices,
diff --git a/arch/sh/boards/mach-sdk7780/irq.c b/arch/sh/boards/mach-sdk7780/irq.c
index 8555581..e5f7564 100644
--- a/arch/sh/boards/mach-sdk7780/irq.c
+++ b/arch/sh/boards/mach-sdk7780/irq.c
@@ -37,9 +37,9 @@
 {
 	printk(KERN_INFO "Using SDK7780 interrupt controller.\n");
 
-	ctrl_outw(0xFFFF, FPGA_IRQ0MR);
+	__raw_writew(0xFFFF, FPGA_IRQ0MR);
 	/* Setup IRL 0-3 */
-	ctrl_outw(0x0003, FPGA_IMSR);
+	__raw_writew(0x0003, FPGA_IMSR);
 	plat_irq_setup_pins(IRQ_MODE_IRL3210);
 
 	register_intc_controller(&fpga_intc_desc);
diff --git a/arch/sh/boards/mach-sdk7780/setup.c b/arch/sh/boards/mach-sdk7780/setup.c
index aad94a7..4da38db 100644
--- a/arch/sh/boards/mach-sdk7780/setup.c
+++ b/arch/sh/boards/mach-sdk7780/setup.c
@@ -20,27 +20,18 @@
 
 #define GPIO_PECR        0xFFEA0008
 
-//* Heartbeat */
-static struct heartbeat_data heartbeat_data = {
-	.regsize = 16,
-};
-
-static struct resource heartbeat_resources[] = {
-	[0] = {
-		.start  = PA_LED,
-		.end    = PA_LED,
-		.flags  = IORESOURCE_MEM,
-	},
+/* Heartbeat */
+static struct resource heartbeat_resource = {
+	.start  = PA_LED,
+	.end    = PA_LED,
+	.flags  = IORESOURCE_MEM | IORESOURCE_MEM_16BIT,
 };
 
 static struct platform_device heartbeat_device = {
 	.name           = "heartbeat",
 	.id             = -1,
-	.dev = {
-		.platform_data = &heartbeat_data,
-	},
-	.num_resources  = ARRAY_SIZE(heartbeat_resources),
-	.resource       = heartbeat_resources,
+	.num_resources  = 1,
+	.resource       = &heartbeat_resource,
 };
 
 /* SMC91x */
@@ -83,8 +74,8 @@
 
 static void __init sdk7780_setup(char **cmdline_p)
 {
-	u16 ver = ctrl_inw(FPGA_FPVERR);
-	u16 dateStamp = ctrl_inw(FPGA_FPDATER);
+	u16 ver = __raw_readw(FPGA_FPVERR);
+	u16 dateStamp = __raw_readw(FPGA_FPDATER);
 
 	printk(KERN_INFO "Renesas Technology Europe SDK7780 support.\n");
 	printk(KERN_INFO "Board version: %d (revision %d), "
@@ -94,7 +85,7 @@
 			 dateStamp);
 
 	/* Setup pin mux'ing for PCIC */
-	ctrl_outw(0x0000, GPIO_PECR);
+	__raw_writew(0x0000, GPIO_PECR);
 }
 
 /*
diff --git a/arch/sh/boards/mach-sdk7786/Makefile b/arch/sh/boards/mach-sdk7786/Makefile
new file mode 100644
index 0000000..a29f19e
--- /dev/null
+++ b/arch/sh/boards/mach-sdk7786/Makefile
@@ -0,0 +1 @@
+obj-y	:= setup.o fpga.o irq.o
diff --git a/arch/sh/boards/mach-sdk7786/fpga.c b/arch/sh/boards/mach-sdk7786/fpga.c
new file mode 100644
index 0000000..3e4ec66
--- /dev/null
+++ b/arch/sh/boards/mach-sdk7786/fpga.c
@@ -0,0 +1,72 @@
+/*
+ * SDK7786 FPGA Support.
+ *
+ * Copyright (C) 2010  Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/bcd.h>
+#include <mach/fpga.h>
+#include <asm/sizes.h>
+
+#define FPGA_REGS_OFFSET	0x03fff800
+#define FPGA_REGS_SIZE		0x490
+
+/*
+ * The FPGA can be mapped in any of the generally available areas,
+ * so we attempt to scan for it using the fixed SRSTR read magic.
+ *
+ * Once the FPGA is located, the rest of the mapping data for the other
+ * components can be determined dynamically from its section mapping
+ * registers.
+ */
+static void __iomem *sdk7786_fpga_probe(void)
+{
+	unsigned long area;
+	void __iomem *base;
+
+	/*
+	 * Iterate over all of the areas where the FPGA could be mapped.
+	 * The possible range is anywhere from area 0 through 6, area 7
+	 * is reserved.
+	 */
+	for (area = PA_AREA0; area < PA_AREA7; area += SZ_64M) {
+		base = ioremap_nocache(area + FPGA_REGS_OFFSET, FPGA_REGS_SIZE);
+		if (!base) {
+			/* Failed to remap this area, move along. */
+			continue;
+		}
+
+		if (ioread16(base + SRSTR) == SRSTR_MAGIC)
+			return base;	/* Found it! */
+
+		iounmap(base);
+	}
+
+	return NULL;
+}
+
+void __iomem *sdk7786_fpga_base;
+
+void __init sdk7786_fpga_init(void)
+{
+	u16 version, date;
+
+	sdk7786_fpga_base = sdk7786_fpga_probe();
+	if (unlikely(!sdk7786_fpga_base)) {
+		panic("FPGA detection failed.\n");
+		return;
+	}
+
+	version = fpga_read_reg(FPGAVR);
+	date = fpga_read_reg(FPGADR);
+
+	pr_info("\tFPGA version:\t%d.%d (built on %d/%d/%d)\n",
+		bcd2bin(version >> 8) & 0xf, bcd2bin(version & 0xf),
+		((date >> 12) & 0xf) + 2000,
+		(date >> 8) & 0xf, bcd2bin(date & 0xff));
+}
diff --git a/arch/sh/boards/mach-sdk7786/irq.c b/arch/sh/boards/mach-sdk7786/irq.c
new file mode 100644
index 0000000..46943a0
--- /dev/null
+++ b/arch/sh/boards/mach-sdk7786/irq.c
@@ -0,0 +1,48 @@
+/*
+ * SDK7786 FPGA IRQ Controller Support.
+ *
+ * Copyright (C) 2010  Matt Fleming
+ * Copyright (C) 2010  Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/irq.h>
+#include <mach/fpga.h>
+#include <mach/irq.h>
+
+enum {
+	ATA_IRQ_BIT		= 1,
+	SPI_BUSY_BIT		= 2,
+	LIRQ5_BIT		= 3,
+	LIRQ6_BIT		= 4,
+	LIRQ7_BIT		= 5,
+	LIRQ8_BIT		= 6,
+	KEY_IRQ_BIT		= 7,
+	PEN_IRQ_BIT		= 8,
+	ETH_IRQ_BIT		= 9,
+	RTC_ALARM_BIT		= 10,
+	CRYSTAL_FAIL_BIT	= 12,
+	ETH_PME_BIT		= 14,
+};
+
+void __init sdk7786_init_irq(void)
+{
+	unsigned int tmp;
+
+	/* Enable priority encoding for all IRLs */
+	fpga_write_reg(fpga_read_reg(INTMSR) | 0x0303, INTMSR);
+
+	/* Clear FPGA interrupt status registers */
+	fpga_write_reg(0x0000, INTASR);
+	fpga_write_reg(0x0000, INTBSR);
+
+	/* Unmask FPGA interrupts */
+	tmp = fpga_read_reg(INTAMR);
+	tmp &= ~(1 << ETH_IRQ_BIT);
+	fpga_write_reg(tmp, INTAMR);
+
+	plat_irq_setup_pins(IRQ_MODE_IRL7654_MASK);
+	plat_irq_setup_pins(IRQ_MODE_IRL3210_MASK);
+}
diff --git a/arch/sh/boards/mach-sdk7786/setup.c b/arch/sh/boards/mach-sdk7786/setup.c
new file mode 100644
index 0000000..f094ea2
--- /dev/null
+++ b/arch/sh/boards/mach-sdk7786/setup.c
@@ -0,0 +1,189 @@
+/*
+ * Renesas Technology Europe SDK7786 Support.
+ *
+ * Copyright (C) 2010  Matt Fleming
+ * Copyright (C) 2010  Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/smsc911x.h>
+#include <linux/i2c.h>
+#include <linux/irq.h>
+#include <linux/clk.h>
+#include <mach/fpga.h>
+#include <mach/irq.h>
+#include <asm/machvec.h>
+#include <asm/heartbeat.h>
+#include <asm/sizes.h>
+#include <asm/reboot.h>
+
+static struct resource heartbeat_resource = {
+	.start		= 0x07fff8b0,
+	.end		= 0x07fff8b0 + sizeof(u16) - 1,
+	.flags		= IORESOURCE_MEM | IORESOURCE_MEM_16BIT,
+};
+
+static struct platform_device heartbeat_device = {
+	.name		= "heartbeat",
+	.id		= -1,
+	.num_resources	= 1,
+	.resource	= &heartbeat_resource,
+};
+
+static struct resource smsc911x_resources[] = {
+	[0] = {
+		.name		= "smsc911x-memory",
+		.start		= 0x07ffff00,
+		.end		= 0x07ffff00 + SZ_256 - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+	[1] = {
+		.name		= "smsc911x-irq",
+		.start		= evt2irq(0x2c0),
+		.end		= evt2irq(0x2c0),
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct smsc911x_platform_config smsc911x_config = {
+	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+	.irq_type	= SMSC911X_IRQ_TYPE_OPEN_DRAIN,
+	.flags		= SMSC911X_USE_32BIT,
+	.phy_interface	= PHY_INTERFACE_MODE_MII,
+};
+
+static struct platform_device smsc911x_device = {
+	.name		= "smsc911x",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(smsc911x_resources),
+	.resource	= smsc911x_resources,
+	.dev = {
+		.platform_data = &smsc911x_config,
+	},
+};
+
+static struct resource smbus_fpga_resource = {
+	.start		= 0x07fff9e0,
+	.end		= 0x07fff9e0 + SZ_32 - 1,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device smbus_fpga_device = {
+	.name		= "i2c-sdk7786",
+	.id		= 0,
+	.num_resources	= 1,
+	.resource	= &smbus_fpga_resource,
+};
+
+static struct resource smbus_pcie_resource = {
+	.start		= 0x07fffc30,
+	.end		= 0x07fffc30 + SZ_32 - 1,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device smbus_pcie_device = {
+	.name		= "i2c-sdk7786",
+	.id		= 1,
+	.num_resources	= 1,
+	.resource	= &smbus_pcie_resource,
+};
+
+static struct i2c_board_info __initdata sdk7786_i2c_devices[] = {
+	{
+		I2C_BOARD_INFO("max6900", 0x68),
+	},
+};
+
+static struct platform_device *sh7786_devices[] __initdata = {
+	&heartbeat_device,
+	&smsc911x_device,
+	&smbus_fpga_device,
+	&smbus_pcie_device,
+};
+
+static int sdk7786_i2c_setup(void)
+{
+	unsigned int tmp;
+
+	/*
+	 * Hand over I2C control to the FPGA.
+	 */
+	tmp = fpga_read_reg(SBCR);
+	tmp &= ~SCBR_I2CCEN;
+	tmp |= SCBR_I2CMEN;
+	fpga_write_reg(tmp, SBCR);
+
+	return i2c_register_board_info(0, sdk7786_i2c_devices,
+				       ARRAY_SIZE(sdk7786_i2c_devices));
+}
+
+static int __init sdk7786_devices_setup(void)
+{
+	int ret;
+
+	ret = platform_add_devices(sh7786_devices, ARRAY_SIZE(sh7786_devices));
+	if (unlikely(ret != 0))
+		return ret;
+
+	return sdk7786_i2c_setup();
+}
+__initcall(sdk7786_devices_setup);
+
+static int sdk7786_mode_pins(void)
+{
+	return fpga_read_reg(MODSWR);
+}
+
+static int sdk7786_clk_init(void)
+{
+	struct clk *clk;
+	int ret;
+
+	/*
+	 * Only handle the EXTAL case, anyone interfacing a crystal
+	 * resonator will need to provide their own input clock.
+	 */
+	if (test_mode_pin(MODE_PIN9))
+		return -EINVAL;
+
+	clk = clk_get(NULL, "extal");
+	if (!clk || IS_ERR(clk))
+		return PTR_ERR(clk);
+	ret = clk_set_rate(clk, 33333333);
+	clk_put(clk);
+
+	return ret;
+}
+
+static void sdk7786_restart(char *cmd)
+{
+	fpga_write_reg(0xa5a5, SRSTR);
+}
+
+/* Initialize the board */
+static void __init sdk7786_setup(char **cmdline_p)
+{
+	pr_info("Renesas Technology Europe SDK7786 support:\n");
+
+	sdk7786_fpga_init();
+
+	pr_info("\tPCB revision:\t%d\n", fpga_read_reg(PCBRR) & 0xf);
+
+	machine_ops.restart = sdk7786_restart;
+}
+
+/*
+ * The Machine Vector
+ */
+static struct sh_machine_vector mv_sdk7786 __initmv = {
+	.mv_name		= "SDK7786",
+	.mv_setup		= sdk7786_setup,
+	.mv_mode_pins		= sdk7786_mode_pins,
+	.mv_clk_init		= sdk7786_clk_init,
+	.mv_init_irq		= sdk7786_init_irq,
+};
diff --git a/arch/sh/boards/mach-se/7206/io.c b/arch/sh/boards/mach-se/7206/io.c
index 1804556..adadc77 100644
--- a/arch/sh/boards/mach-se/7206/io.c
+++ b/arch/sh/boards/mach-se/7206/io.c
@@ -16,7 +16,7 @@
 
 static inline void delay(void)
 {
-	ctrl_inw(0x20000000);  /* P2 ROM Area */
+	__raw_readw(0x20000000);  /* P2 ROM Area */
 }
 
 /* MS7750 requires special versions of in*, out* routines, since
diff --git a/arch/sh/boards/mach-se/7206/irq.c b/arch/sh/boards/mach-se/7206/irq.c
index aef7f05..8d82175 100644
--- a/arch/sh/boards/mach-se/7206/irq.c
+++ b/arch/sh/boards/mach-se/7206/irq.c
@@ -32,12 +32,12 @@
 	unsigned short msk0,msk1;
 
 	/* Set the priority in IPR to 0 */
-	val = ctrl_inw(INTC_IPR01);
+	val = __raw_readw(INTC_IPR01);
 	val &= mask;
-	ctrl_outw(val, INTC_IPR01);
+	__raw_writew(val, INTC_IPR01);
 	/* FPGA mask set */
-	msk0 = ctrl_inw(INTMSK0);
-	msk1 = ctrl_inw(INTMSK1);
+	msk0 = __raw_readw(INTMSK0);
+	msk1 = __raw_readw(INTMSK1);
 
 	switch (irq) {
 	case IRQ0_IRQ:
@@ -51,8 +51,8 @@
 		msk1 |= 0x00ff;
 		break;
 	}
-	ctrl_outw(msk0, INTMSK0);
-	ctrl_outw(msk1, INTMSK1);
+	__raw_writew(msk0, INTMSK0);
+	__raw_writew(msk1, INTMSK1);
 }
 
 static void enable_se7206_irq(unsigned int irq)
@@ -62,13 +62,13 @@
 	unsigned short msk0,msk1;
 
 	/* Set priority in IPR back to original value */
-	val = ctrl_inw(INTC_IPR01);
+	val = __raw_readw(INTC_IPR01);
 	val |= value;
-	ctrl_outw(val, INTC_IPR01);
+	__raw_writew(val, INTC_IPR01);
 
 	/* FPGA mask reset */
-	msk0 = ctrl_inw(INTMSK0);
-	msk1 = ctrl_inw(INTMSK1);
+	msk0 = __raw_readw(INTMSK0);
+	msk1 = __raw_readw(INTMSK1);
 
 	switch (irq) {
 	case IRQ0_IRQ:
@@ -82,19 +82,20 @@
 		msk1 &= ~0x00ff;
 		break;
 	}
-	ctrl_outw(msk0, INTMSK0);
-	ctrl_outw(msk1, INTMSK1);
+	__raw_writew(msk0, INTMSK0);
+	__raw_writew(msk1, INTMSK1);
 }
 
 static void eoi_se7206_irq(unsigned int irq)
 {
 	unsigned short sts0,sts1;
+	struct irq_desc *desc = irq_to_desc(irq);
 
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+	if (!(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
 		enable_se7206_irq(irq);
 	/* FPGA isr clear */
-	sts0 = ctrl_inw(INTSTS0);
-	sts1 = ctrl_inw(INTSTS1);
+	sts0 = __raw_readw(INTSTS0);
+	sts1 = __raw_readw(INTSTS1);
 
 	switch (irq) {
 	case IRQ0_IRQ:
@@ -108,8 +109,8 @@
 		sts1 &= ~0x00ff;
 		break;
 	}
-	ctrl_outw(sts0, INTSTS0);
-	ctrl_outw(sts1, INTSTS1);
+	__raw_writew(sts0, INTSTS0);
+	__raw_writew(sts1, INTSTS1);
 }
 
 static struct irq_chip se7206_irq_chip __read_mostly = {
@@ -136,11 +137,11 @@
 	make_se7206_irq(IRQ0_IRQ); /* SMC91C111 */
 	make_se7206_irq(IRQ1_IRQ); /* ATA */
 	make_se7206_irq(IRQ3_IRQ); /* SLOT / PCM */
-	ctrl_outw(inw(INTC_ICR1) | 0x000b ,INTC_ICR1 ) ; /* ICR1 */
+	__raw_writew(inw(INTC_ICR1) | 0x000b ,INTC_ICR1 ) ; /* ICR1 */
 
 	/* FPGA System register setup*/
-	ctrl_outw(0x0000,INTSTS0); /* Clear INTSTS0 */
-	ctrl_outw(0x0000,INTSTS1); /* Clear INTSTS1 */
+	__raw_writew(0x0000,INTSTS0); /* Clear INTSTS0 */
+	__raw_writew(0x0000,INTSTS1); /* Clear INTSTS1 */
 	/* IRQ0=LAN, IRQ1=ATA, IRQ3=SLT,PCM */
-	ctrl_outw(0x0001,INTSEL);
+	__raw_writew(0x0001,INTSEL);
 }
diff --git a/arch/sh/boards/mach-se/7206/setup.c b/arch/sh/boards/mach-se/7206/setup.c
index f5466384..8f5c65d 100644
--- a/arch/sh/boards/mach-se/7206/setup.c
+++ b/arch/sh/boards/mach-se/7206/setup.c
@@ -50,15 +50,12 @@
 static struct heartbeat_data heartbeat_data = {
 	.bit_pos	= heartbeat_bit_pos,
 	.nr_bits	= ARRAY_SIZE(heartbeat_bit_pos),
-	.regsize	= 32,
 };
 
-static struct resource heartbeat_resources[] = {
-	[0] = {
-		.start	= PA_LED,
-		.end	= PA_LED,
-		.flags	= IORESOURCE_MEM,
-	},
+static struct resource heartbeat_resource = {
+	.start	= PA_LED,
+	.end	= PA_LED,
+	.flags	= IORESOURCE_MEM | IORESOURCE_MEM_32BIT,
 };
 
 static struct platform_device heartbeat_device = {
@@ -67,8 +64,8 @@
 	.dev	= {
 		.platform_data	= &heartbeat_data,
 	},
-	.num_resources	= ARRAY_SIZE(heartbeat_resources),
-	.resource	= heartbeat_resources,
+	.num_resources	= 1,
+	.resource	= &heartbeat_resource,
 };
 
 static struct platform_device *se7206_devices[] __initdata = {
diff --git a/arch/sh/boards/mach-se/7343/irq.c b/arch/sh/boards/mach-se/7343/irq.c
index 051c29d..d4305c2 100644
--- a/arch/sh/boards/mach-se/7343/irq.c
+++ b/arch/sh/boards/mach-se/7343/irq.c
@@ -16,16 +16,18 @@
 #include <linux/io.h>
 #include <mach-se/mach/se7343.h>
 
+unsigned int se7343_fpga_irq[SE7343_FPGA_IRQ_NR] = { 0, };
+
 static void disable_se7343_irq(unsigned int irq)
 {
-	unsigned int bit = irq - SE7343_FPGA_IRQ_BASE;
-	ctrl_outw(ctrl_inw(PA_CPLD_IMSK) | 1 << bit, PA_CPLD_IMSK);
+	unsigned int bit = (unsigned int)get_irq_chip_data(irq);
+	__raw_writew(__raw_readw(PA_CPLD_IMSK) | 1 << bit, PA_CPLD_IMSK);
 }
 
 static void enable_se7343_irq(unsigned int irq)
 {
-	unsigned int bit = irq - SE7343_FPGA_IRQ_BASE;
-	ctrl_outw(ctrl_inw(PA_CPLD_IMSK) & ~(1 << bit), PA_CPLD_IMSK);
+	unsigned int bit = (unsigned int)get_irq_chip_data(irq);
+	__raw_writew(__raw_readw(PA_CPLD_IMSK) & ~(1 << bit), PA_CPLD_IMSK);
 }
 
 static struct irq_chip se7343_irq_chip __read_mostly = {
@@ -37,19 +39,16 @@
 
 static void se7343_irq_demux(unsigned int irq, struct irq_desc *desc)
 {
-	unsigned short intv = ctrl_inw(PA_CPLD_ST);
-	struct irq_desc *ext_desc;
-	unsigned int ext_irq = SE7343_FPGA_IRQ_BASE;
+	unsigned short intv = __raw_readw(PA_CPLD_ST);
+	unsigned int ext_irq = 0;
 
 	intv &= (1 << SE7343_FPGA_IRQ_NR) - 1;
 
-	while (intv) {
-		if (intv & 1) {
-			ext_desc = irq_desc + ext_irq;
-			handle_level_irq(ext_irq, ext_desc);
-		}
-		intv >>= 1;
-		ext_irq++;
+	for (; intv; intv >>= 1, ext_irq++) {
+		if (!(intv & 1))
+			continue;
+
+		generic_handle_irq(se7343_fpga_irq[ext_irq]);
 	}
 }
 
@@ -58,16 +57,24 @@
  */
 void __init init_7343se_IRQ(void)
 {
-	int i;
+	int i, irq;
 
-	ctrl_outw(0, PA_CPLD_IMSK);	/* disable all irqs */
-	ctrl_outw(0x2000, 0xb03fffec);	/* mrshpc irq enable */
+	__raw_writew(0, PA_CPLD_IMSK);	/* disable all irqs */
+	__raw_writew(0x2000, 0xb03fffec);	/* mrshpc irq enable */
 
-	for (i = 0; i < SE7343_FPGA_IRQ_NR; i++)
-		set_irq_chip_and_handler_name(SE7343_FPGA_IRQ_BASE + i,
+	for (i = 0; i < SE7343_FPGA_IRQ_NR; i++) {
+		irq = create_irq();
+		if (irq < 0)
+			return;
+		se7343_fpga_irq[i] = irq;
+
+		set_irq_chip_and_handler_name(se7343_fpga_irq[i],
 					      &se7343_irq_chip,
 					      handle_level_irq, "level");
 
+		set_irq_chip_data(se7343_fpga_irq[i], (void *)i);
+	}
+
 	set_irq_chained_handler(IRQ0_IRQ, se7343_irq_demux);
 	set_irq_type(IRQ0_IRQ, IRQ_TYPE_LEVEL_LOW);
 	set_irq_chained_handler(IRQ1_IRQ, se7343_irq_demux);
diff --git a/arch/sh/boards/mach-se/7343/setup.c b/arch/sh/boards/mach-se/7343/setup.c
index 4de56f3..d2370af 100644
--- a/arch/sh/boards/mach-se/7343/setup.c
+++ b/arch/sh/boards/mach-se/7343/setup.c
@@ -11,26 +11,17 @@
 #include <asm/irq.h>
 #include <asm/io.h>
 
-static struct resource heartbeat_resources[] = {
-	[0] = {
-		.start	= PA_LED,
-		.end	= PA_LED,
-		.flags	= IORESOURCE_MEM,
-	},
-};
-
-static struct heartbeat_data heartbeat_data = {
-	.regsize = 16,
+static struct resource heartbeat_resource = {
+	.start	= PA_LED,
+	.end	= PA_LED,
+	.flags	= IORESOURCE_MEM | IORESOURCE_MEM_16BIT,
 };
 
 static struct platform_device heartbeat_device = {
 	.name		= "heartbeat",
 	.id		= -1,
-	.dev = {
-		.platform_data = &heartbeat_data,
-	},
-	.num_resources	= ARRAY_SIZE(heartbeat_resources),
-	.resource	= heartbeat_resources,
+	.num_resources	= 1,
+	.resource	= &heartbeat_resource,
 };
 
 static struct mtd_partition nor_flash_partitions[] = {
@@ -82,7 +73,6 @@
 		.mapbase	= 0x16000000,
 		.regshift	= 1,
 		.flags		= ST16C2550C_FLAGS,
-		.irq		= UARTA_IRQ,
 		.uartclk	= 7372800,
 	},
 	[1] = {
@@ -90,7 +80,6 @@
 		.mapbase	= 0x17000000,
 		.regshift	= 1,
 		.flags		= ST16C2550C_FLAGS,
-		.irq		= UARTB_IRQ,
 		.uartclk	= 7372800,
 	},
 	{ },
@@ -121,7 +110,7 @@
 		.flags  = IORESOURCE_MEM,
 	},
 	[2] = {
-		.start  = USB_IRQ,
+		/* Filled in later */
 		.flags  = IORESOURCE_IRQ,
 	},
 };
@@ -138,8 +127,8 @@
 static struct platform_device usb_device = {
 	.name			= "isp116x-hcd",
 	.id			= -1,
-	.num_resources  	= ARRAY_SIZE(usb_resources),
-	.resource       	= usb_resources,
+	.num_resources		= ARRAY_SIZE(usb_resources),
+	.resource		= usb_resources,
 	.dev			= {
 		.platform_data	= &usb_platform_data,
 	},
@@ -155,6 +144,13 @@
 
 static int __init sh7343se_devices_setup(void)
 {
+	/* Wire-up dynamic vectors */
+	serial_platform_data[0].irq = se7343_fpga_irq[SE7343_FPGA_IRQ_UARTA];
+	serial_platform_data[1].irq = se7343_fpga_irq[SE7343_FPGA_IRQ_UARTB];
+
+	usb_resources[2].start = usb_resources[2].end =
+		se7343_fpga_irq[SE7343_FPGA_IRQ_USB];
+
 	return platform_add_devices(sh7343se_platform_devices,
 				    ARRAY_SIZE(sh7343se_platform_devices));
 }
@@ -165,10 +161,10 @@
  */
 static void __init sh7343se_setup(char **cmdline_p)
 {
-	ctrl_outw(0xf900, FPGA_OUT);	/* FPGA */
+	__raw_writew(0xf900, FPGA_OUT);	/* FPGA */
 
-	ctrl_outw(0x0002, PORT_PECR);	/* PORT E 1 = IRQ5 */
-	ctrl_outw(0x0020, PORT_PSELD);
+	__raw_writew(0x0002, PORT_PECR);	/* PORT E 1 = IRQ5 */
+	__raw_writew(0x0020, PORT_PSELD);
 
 	printk(KERN_INFO "MS7343CP01 Setup...done\n");
 }
@@ -179,6 +175,5 @@
 static struct sh_machine_vector mv_7343se __initmv = {
 	.mv_name = "SolutionEngine 7343",
 	.mv_setup = sh7343se_setup,
-	.mv_nr_irqs = SE7343_FPGA_IRQ_BASE + SE7343_FPGA_IRQ_NR,
 	.mv_init_irq = init_7343se_IRQ,
 };
diff --git a/arch/sh/boards/mach-se/770x/irq.c b/arch/sh/boards/mach-se/770x/irq.c
index ec1fea5..1028c17 100644
--- a/arch/sh/boards/mach-se/770x/irq.c
+++ b/arch/sh/boards/mach-se/770x/irq.c
@@ -96,13 +96,13 @@
 void __init init_se_IRQ(void)
 {
 	/* Disable all interrupts */
-	ctrl_outw(0, BCR_ILCRA);
-	ctrl_outw(0, BCR_ILCRB);
-	ctrl_outw(0, BCR_ILCRC);
-	ctrl_outw(0, BCR_ILCRD);
-	ctrl_outw(0, BCR_ILCRE);
-	ctrl_outw(0, BCR_ILCRF);
-	ctrl_outw(0, BCR_ILCRG);
+	__raw_writew(0, BCR_ILCRA);
+	__raw_writew(0, BCR_ILCRB);
+	__raw_writew(0, BCR_ILCRC);
+	__raw_writew(0, BCR_ILCRD);
+	__raw_writew(0, BCR_ILCRE);
+	__raw_writew(0, BCR_ILCRF);
+	__raw_writew(0, BCR_ILCRG);
 
 	register_ipr_controller(&ipr_irq_desc);
 }
diff --git a/arch/sh/boards/mach-se/770x/setup.c b/arch/sh/boards/mach-se/770x/setup.c
index 527eb6b..66d39d1 100644
--- a/arch/sh/boards/mach-se/770x/setup.c
+++ b/arch/sh/boards/mach-se/770x/setup.c
@@ -93,15 +93,12 @@
 static struct heartbeat_data heartbeat_data = {
 	.bit_pos	= heartbeat_bit_pos,
 	.nr_bits	= ARRAY_SIZE(heartbeat_bit_pos),
-	.regsize	= 16,
 };
 
-static struct resource heartbeat_resources[] = {
-	[0] = {
-		.start	= PA_LED,
-		.end	= PA_LED,
-		.flags	= IORESOURCE_MEM,
-	},
+static struct resource heartbeat_resource = {
+	.start	= PA_LED,
+	.end	= PA_LED,
+	.flags	= IORESOURCE_MEM | IORESOURCE_MEM_16BIT,
 };
 
 static struct platform_device heartbeat_device = {
@@ -110,8 +107,8 @@
 	.dev	= {
 		.platform_data	= &heartbeat_data,
 	},
-	.num_resources	= ARRAY_SIZE(heartbeat_resources),
-	.resource	= heartbeat_resources,
+	.num_resources	= 1,
+	.resource	= &heartbeat_resource,
 };
 
 #if defined(CONFIG_CPU_SUBTYPE_SH7710) ||\
diff --git a/arch/sh/boards/mach-se/7721/irq.c b/arch/sh/boards/mach-se/7721/irq.c
index b417acc..d85022e 100644
--- a/arch/sh/boards/mach-se/7721/irq.c
+++ b/arch/sh/boards/mach-se/7721/irq.c
@@ -38,7 +38,7 @@
 void __init init_se7721_IRQ(void)
 {
 	/* PPCR */
-	ctrl_outw(ctrl_inw(0xa4050118) & ~0x00ff, 0xa4050118);
+	__raw_writew(__raw_readw(0xa4050118) & ~0x00ff, 0xa4050118);
 
 	register_intc_controller(&intc_desc);
 	intc_set_priority(MRSHPC_IRQ0, 0xf - MRSHPC_IRQ0);
diff --git a/arch/sh/boards/mach-se/7721/setup.c b/arch/sh/boards/mach-se/7721/setup.c
index 55af4c3..7416ad7 100644
--- a/arch/sh/boards/mach-se/7721/setup.c
+++ b/arch/sh/boards/mach-se/7721/setup.c
@@ -23,15 +23,12 @@
 static struct heartbeat_data heartbeat_data = {
 	.bit_pos	= heartbeat_bit_pos,
 	.nr_bits	= ARRAY_SIZE(heartbeat_bit_pos),
-	.regsize	= 16,
 };
 
-static struct resource heartbeat_resources[] = {
-	[0] = {
-		.start	= PA_LED,
-		.end	= PA_LED,
-		.flags	= IORESOURCE_MEM,
-	},
+static struct resource heartbeat_resource = {
+	.start	= PA_LED,
+	.end	= PA_LED,
+	.flags	= IORESOURCE_MEM | IORESOURCE_MEM_16BIT,
 };
 
 static struct platform_device heartbeat_device = {
@@ -40,8 +37,8 @@
 	.dev	= {
 		.platform_data	= &heartbeat_data,
 	},
-	.num_resources	= ARRAY_SIZE(heartbeat_resources),
-	.resource	= heartbeat_resources,
+	.num_resources	= 1,
+	.resource	= &heartbeat_resource,
 };
 
 static struct resource cf_ide_resources[] = {
@@ -83,10 +80,10 @@
 static void __init se7721_setup(char **cmdline_p)
 {
 	/* for USB */
-	ctrl_outw(0x0000, 0xA405010C);	/* PGCR */
-	ctrl_outw(0x0000, 0xA405010E);	/* PHCR */
-	ctrl_outw(0x00AA, 0xA4050118);	/* PPCR */
-	ctrl_outw(0x0000, 0xA4050124);	/* PSELA */
+	__raw_writew(0x0000, 0xA405010C);	/* PGCR */
+	__raw_writew(0x0000, 0xA405010E);	/* PHCR */
+	__raw_writew(0x00AA, 0xA4050118);	/* PPCR */
+	__raw_writew(0x0000, 0xA4050124);	/* PSELA */
 }
 
 /*
diff --git a/arch/sh/boards/mach-se/7722/irq.c b/arch/sh/boards/mach-se/7722/irq.c
index b221b68..61605db 100644
--- a/arch/sh/boards/mach-se/7722/irq.c
+++ b/arch/sh/boards/mach-se/7722/irq.c
@@ -21,13 +21,13 @@
 static void disable_se7722_irq(unsigned int irq)
 {
 	unsigned int bit = (unsigned int)get_irq_chip_data(irq);
-	ctrl_outw(ctrl_inw(IRQ01_MASK) | 1 << bit, IRQ01_MASK);
+	__raw_writew(__raw_readw(IRQ01_MASK) | 1 << bit, IRQ01_MASK);
 }
 
 static void enable_se7722_irq(unsigned int irq)
 {
 	unsigned int bit = (unsigned int)get_irq_chip_data(irq);
-	ctrl_outw(ctrl_inw(IRQ01_MASK) & ~(1 << bit), IRQ01_MASK);
+	__raw_writew(__raw_readw(IRQ01_MASK) & ~(1 << bit), IRQ01_MASK);
 }
 
 static struct irq_chip se7722_irq_chip __read_mostly = {
@@ -39,7 +39,7 @@
 
 static void se7722_irq_demux(unsigned int irq, struct irq_desc *desc)
 {
-	unsigned short intv = ctrl_inw(IRQ01_STS);
+	unsigned short intv = __raw_readw(IRQ01_STS);
 	unsigned int ext_irq = 0;
 
 	intv &= (1 << SE7722_FPGA_IRQ_NR) - 1;
@@ -59,8 +59,8 @@
 {
 	int i, irq;
 
-	ctrl_outw(0, IRQ01_MASK);       /* disable all irqs */
-	ctrl_outw(0x2000, 0xb03fffec);  /* mrshpc irq enable */
+	__raw_writew(0, IRQ01_MASK);       /* disable all irqs */
+	__raw_writew(0x2000, 0xb03fffec);  /* mrshpc irq enable */
 
 	for (i = 0; i < SE7722_FPGA_IRQ_NR; i++) {
 		irq = create_irq();
diff --git a/arch/sh/boards/mach-se/7722/setup.c b/arch/sh/boards/mach-se/7722/setup.c
index b1cb942..80a4e57 100644
--- a/arch/sh/boards/mach-se/7722/setup.c
+++ b/arch/sh/boards/mach-se/7722/setup.c
@@ -25,26 +25,17 @@
 #include <cpu/sh7722.h>
 
 /* Heartbeat */
-static struct heartbeat_data heartbeat_data = {
-	.regsize = 16,
-};
-
-static struct resource heartbeat_resources[] = {
-	[0] = {
-		.start  = PA_LED,
-		.end    = PA_LED,
-		.flags  = IORESOURCE_MEM,
-	},
+static struct resource heartbeat_resource = {
+	.start  = PA_LED,
+	.end    = PA_LED,
+	.flags  = IORESOURCE_MEM | IORESOURCE_MEM_16BIT,
 };
 
 static struct platform_device heartbeat_device = {
 	.name           = "heartbeat",
 	.id             = -1,
-	.dev = {
-		.platform_data = &heartbeat_data,
-	},
-	.num_resources  = ARRAY_SIZE(heartbeat_resources),
-	.resource       = heartbeat_resources,
+	.num_resources  = 1,
+	.resource       = &heartbeat_resource,
 };
 
 /* SMC91x */
@@ -165,32 +156,32 @@
 
 static void __init se7722_setup(char **cmdline_p)
 {
-	ctrl_outw(0x010D, FPGA_OUT);    /* FPGA */
+	__raw_writew(0x010D, FPGA_OUT);    /* FPGA */
 
-	ctrl_outw(0x0000, PORT_PECR);   /* PORT E 1 = IRQ5 ,E 0 = BS */
-	ctrl_outw(0x1000, PORT_PJCR);   /* PORT J 1 = IRQ1,J 0 =IRQ0 */
+	__raw_writew(0x0000, PORT_PECR);   /* PORT E 1 = IRQ5 ,E 0 = BS */
+	__raw_writew(0x1000, PORT_PJCR);   /* PORT J 1 = IRQ1,J 0 =IRQ0 */
 
 	/* LCDC I/O */
-	ctrl_outw(0x0020, PORT_PSELD);
+	__raw_writew(0x0020, PORT_PSELD);
 
 	/* SIOF1*/
-	ctrl_outw(0x0003, PORT_PSELB);
-	ctrl_outw(0xe000, PORT_PSELC);
-	ctrl_outw(0x0000, PORT_PKCR);
+	__raw_writew(0x0003, PORT_PSELB);
+	__raw_writew(0xe000, PORT_PSELC);
+	__raw_writew(0x0000, PORT_PKCR);
 
 	/* LCDC */
-	ctrl_outw(0x4020, PORT_PHCR);
-	ctrl_outw(0x0000, PORT_PLCR);
-	ctrl_outw(0x0000, PORT_PMCR);
-	ctrl_outw(0x0002, PORT_PRCR);
-	ctrl_outw(0x0000, PORT_PXCR);   /* LCDC,CS6A */
+	__raw_writew(0x4020, PORT_PHCR);
+	__raw_writew(0x0000, PORT_PLCR);
+	__raw_writew(0x0000, PORT_PMCR);
+	__raw_writew(0x0002, PORT_PRCR);
+	__raw_writew(0x0000, PORT_PXCR);   /* LCDC,CS6A */
 
 	/* KEYSC */
-	ctrl_outw(0x0A10, PORT_PSELA); /* BS,SHHID2 */
-	ctrl_outw(0x0000, PORT_PYCR);
-	ctrl_outw(0x0000, PORT_PZCR);
-	ctrl_outw(ctrl_inw(PORT_HIZCRA) & ~0x4000, PORT_HIZCRA);
-	ctrl_outw(ctrl_inw(PORT_HIZCRC) & ~0xc000, PORT_HIZCRC);
+	__raw_writew(0x0A10, PORT_PSELA); /* BS,SHHID2 */
+	__raw_writew(0x0000, PORT_PYCR);
+	__raw_writew(0x0000, PORT_PZCR);
+	__raw_writew(__raw_readw(PORT_HIZCRA) & ~0x4000, PORT_HIZCRA);
+	__raw_writew(__raw_readw(PORT_HIZCRC) & ~0xc000, PORT_HIZCRC);
 }
 
 /*
diff --git a/arch/sh/boards/mach-se/7724/irq.c b/arch/sh/boards/mach-se/7724/irq.c
index f76cf3b..0942be2 100644
--- a/arch/sh/boards/mach-se/7724/irq.c
+++ b/arch/sh/boards/mach-se/7724/irq.c
@@ -72,14 +72,14 @@
 {
 	struct fpga_irq set = get_fpga_irq(fpga2irq(irq));
 	unsigned int bit = irq - set.base;
-	ctrl_outw(ctrl_inw(set.mraddr) | 0x0001 << bit, set.mraddr);
+	__raw_writew(__raw_readw(set.mraddr) | 0x0001 << bit, set.mraddr);
 }
 
 static void enable_se7724_irq(unsigned int irq)
 {
 	struct fpga_irq set = get_fpga_irq(fpga2irq(irq));
 	unsigned int bit = irq - set.base;
-	ctrl_outw(ctrl_inw(set.mraddr) & ~(0x0001 << bit), set.mraddr);
+	__raw_writew(__raw_readw(set.mraddr) & ~(0x0001 << bit), set.mraddr);
 }
 
 static struct irq_chip se7724_irq_chip __read_mostly = {
@@ -92,19 +92,16 @@
 static void se7724_irq_demux(unsigned int irq, struct irq_desc *desc)
 {
 	struct fpga_irq set = get_fpga_irq(irq);
-	unsigned short intv = ctrl_inw(set.sraddr);
-	struct irq_desc *ext_desc;
+	unsigned short intv = __raw_readw(set.sraddr);
 	unsigned int ext_irq = set.base;
 
 	intv &= set.mask;
 
-	while (intv) {
-		if (intv & 0x0001) {
-			ext_desc = irq_desc + ext_irq;
-			handle_level_irq(ext_irq, ext_desc);
-		}
-		intv >>= 1;
-		ext_irq++;
+	for (; intv; intv >>= 1, ext_irq++) {
+		if (!(intv & 1))
+			continue;
+
+		generic_handle_irq(ext_irq);
 	}
 }
 
@@ -113,20 +110,39 @@
  */
 void __init init_se7724_IRQ(void)
 {
-	int i;
+	int i, nid = cpu_to_node(boot_cpu_data);
 
-	ctrl_outw(0xffff, IRQ0_MR);  /* mask all */
-	ctrl_outw(0xffff, IRQ1_MR);  /* mask all */
-	ctrl_outw(0xffff, IRQ2_MR);  /* mask all */
-	ctrl_outw(0x0000, IRQ0_SR);  /* clear irq */
-	ctrl_outw(0x0000, IRQ1_SR);  /* clear irq */
-	ctrl_outw(0x0000, IRQ2_SR);  /* clear irq */
-	ctrl_outw(0x002a, IRQ_MODE); /* set irq type */
+	__raw_writew(0xffff, IRQ0_MR);  /* mask all */
+	__raw_writew(0xffff, IRQ1_MR);  /* mask all */
+	__raw_writew(0xffff, IRQ2_MR);  /* mask all */
+	__raw_writew(0x0000, IRQ0_SR);  /* clear irq */
+	__raw_writew(0x0000, IRQ1_SR);  /* clear irq */
+	__raw_writew(0x0000, IRQ2_SR);  /* clear irq */
+	__raw_writew(0x002a, IRQ_MODE); /* set irq type */
 
-	for (i = 0; i < SE7724_FPGA_IRQ_NR; i++)
-		set_irq_chip_and_handler_name(SE7724_FPGA_IRQ_BASE + i,
+	for (i = 0; i < SE7724_FPGA_IRQ_NR; i++) {
+		int irq, wanted;
+
+		wanted = SE7724_FPGA_IRQ_BASE + i;
+
+		irq = create_irq_nr(wanted, nid);
+		if (unlikely(irq == 0)) {
+			pr_err("%s: failed hooking irq %d for FPGA\n",
+			       __func__, wanted);
+			return;
+		}
+
+		if (unlikely(irq != wanted)) {
+			pr_err("%s: got irq %d but wanted %d, bailing.\n",
+			       __func__, irq, wanted);
+			destroy_irq(irq);
+			return;
+		}
+
+		set_irq_chip_and_handler_name(irq,
 					      &se7724_irq_chip,
 					      handle_level_irq, "level");
+	}
 
 	set_irq_chained_handler(IRQ0_IRQ, se7724_irq_demux);
 	set_irq_type(IRQ0_IRQ, IRQ_TYPE_LEVEL_LOW);
diff --git a/arch/sh/boards/mach-se/7724/sdram.S b/arch/sh/boards/mach-se/7724/sdram.S
index 9040167..6fa4734 100644
--- a/arch/sh/boards/mach-se/7724/sdram.S
+++ b/arch/sh/boards/mach-se/7724/sdram.S
@@ -39,6 +39,10 @@
 
 	/* DBSC: put memory in auto-refresh mode */
 
+	mov.l	@(SH_SLEEP_MODE, r5), r0
+	tst	#SUSP_SH_RSTANDBY, r0
+	bf	resume_rstandby
+
 	ED 0xFD000040, 0x00000000 /* DBRFPDN0 */
 	WAIT 1
 	ED 0xFD000014, 0x00000002 /* DBCMDCNT (PALL) */
@@ -49,4 +53,79 @@
 	rts
 	 nop
 
+resume_rstandby:
+
+	/* CPG: setup clocks before restarting external memory */
+
+	ED 0xA4150024, 0x00004000 /* PLLCR */
+
+	mov.l	FRQCRA,r0
+	mov.l	@r0,r3
+	mov.l	KICK,r1
+	or	r1, r3
+	mov.l	r3, @r0
+
+	mov.l	LSTATS,r0
+	mov	#1,r1
+WAIT_LSTATS:
+	mov.l	@r0,r3
+	tst	r1,r3
+	bf	WAIT_LSTATS
+
+	/* DBSC: re-initialize and put in auto-refresh */
+
+	ED 0xFD000108, 0x00000181 /* DBPDCNT0 */
+	ED 0xFD000020, 0x015B0002 /* DBCONF */
+	ED 0xFD000030, 0x03071502 /* DBTR0 */
+	ED 0xFD000034, 0x02020102 /* DBTR1 */
+	ED 0xFD000038, 0x01090405 /* DBTR2 */
+	ED 0xFD00003C, 0x00000002 /* DBTR3 */
+	ED 0xFD000008, 0x00000005 /* DBKIND */
+	ED 0xFD000040, 0x00000001 /* DBRFPDN0 */
+	ED 0xFD000040, 0x00000000 /* DBRFPDN0 */
+	ED 0xFD000018, 0x00000001 /* DBCKECNT */
+
+	mov	#100,r0
+WAIT_400NS:
+	dt	r0
+	bf	WAIT_400NS
+
+	ED 0xFD000014, 0x00000002 /* DBCMDCNT (PALL) */
+	ED 0xFD000060, 0x00020000 /* DBMRCNT (EMR2) */
+	ED 0xFD000060, 0x00030000 /* DBMRCNT (EMR3) */
+	ED 0xFD000060, 0x00010004 /* DBMRCNT (EMR) */
+	ED 0xFD000060, 0x00000532 /* DBMRCNT (MRS) */
+	ED 0xFD000014, 0x00000002 /* DBCMDCNT (PALL) */
+	ED 0xFD000014, 0x00000004 /* DBCMDCNT (REF) */
+	ED 0xFD000014, 0x00000004 /* DBCMDCNT (REF) */
+	ED 0xFD000060, 0x00000432 /* DBMRCNT (MRS) */
+	ED 0xFD000060, 0x000103c0 /* DBMRCNT (EMR) */
+	ED 0xFD000060, 0x00010040 /* DBMRCNT (EMR) */
+
+	mov	#100,r0
+WAIT_400NS_2:
+	dt	r0
+	bf	WAIT_400NS_2
+
+	ED 0xFD000010, 0x00000001 /* DBEN */
+	ED 0xFD000044, 0x0000050f /* DBRFPDN1 */
+	ED 0xFD000048, 0x236800e6 /* DBRFPDN2 */
+
+	mov.l	DUMMY,r0
+	mov.l	@r0, r1 /* force single dummy read */
+
+	ED 0xFD000014, 0x00000002 /* DBCMDCNT (PALL) */
+	ED 0xFD000014, 0x00000004 /* DBCMDCNT (REF) */
+	ED 0xFD000108, 0x00000080 /* DBPDCNT0 */
+	ED 0xFD000040, 0x00010000 /* DBRFPDN0 */
+
+	rts
+	 nop
+
+	.balign 4
+DUMMY:	.long	0xac400000
+FRQCRA:	.long	0xa4150000
+KICK:	.long	0x80000000
+LSTATS:	.long	0xa4150060
+
 ENTRY(ms7724se_sdram_leave_end)
diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c
index 858ecb2..66cdbc3 100644
--- a/arch/sh/boards/mach-se/7724/setup.c
+++ b/arch/sh/boards/mach-se/7724/setup.c
@@ -53,26 +53,17 @@
  */
 
 /* Heartbeat */
-static struct heartbeat_data heartbeat_data = {
-	.regsize = 16,
-};
-
-static struct resource heartbeat_resources[] = {
-	[0] = {
-		.start  = PA_LED,
-		.end    = PA_LED,
-		.flags  = IORESOURCE_MEM,
-	},
+static struct resource heartbeat_resource = {
+	.start  = PA_LED,
+	.end    = PA_LED,
+	.flags  = IORESOURCE_MEM | IORESOURCE_MEM_16BIT,
 };
 
 static struct platform_device heartbeat_device = {
 	.name           = "heartbeat",
 	.id             = -1,
-	.dev = {
-		.platform_data = &heartbeat_data,
-	},
-	.num_resources  = ARRAY_SIZE(heartbeat_resources),
-	.resource       = heartbeat_resources,
+	.num_resources  = 1,
+	.resource       = &heartbeat_resource,
 };
 
 /* LAN91C111 */
@@ -265,12 +256,12 @@
 #define FCLKACR		0xa4150008
 static void fsimck_init(struct clk *clk)
 {
-	u32 status = ctrl_inl(clk->enable_reg);
+	u32 status = __raw_readl(clk->enable_reg);
 
 	/* use external clock */
 	status &= ~0x000000ff;
 	status |= 0x00000080;
-	ctrl_outl(status, clk->enable_reg);
+	__raw_writel(status, clk->enable_reg);
 }
 
 static struct clk_ops fsimck_clk_ops = {
@@ -322,7 +313,7 @@
 /* KEYSC in SoC (Needs SW33-2 set to ON) */
 static struct sh_keysc_info keysc_info = {
 	.mode = SH_KEYSC_MODE_1,
-	.scan_timing = 10,
+	.scan_timing = 3,
 	.delay = 50,
 	.keycodes = {
 		KEY_1, KEY_2, KEY_3, KEY_4, KEY_5,
@@ -460,7 +451,7 @@
 		.flags  = IORESOURCE_MEM,
 	},
 	[1] = {
-		.start  = 101,
+		.start  = 100,
 		.flags  = IORESOURCE_IRQ,
 	},
 };
@@ -483,7 +474,7 @@
 		.flags  = IORESOURCE_MEM,
 	},
 	[1] = {
-		.start  = 24,
+		.start  = 23,
 		.flags  = IORESOURCE_IRQ,
 	},
 };
@@ -498,6 +489,26 @@
 	},
 };
 
+/* IrDA */
+static struct resource irda_resources[] = {
+	[0] = {
+		.name	= "IrDA",
+		.start  = 0xA45D0000,
+		.end    = 0xA45D0049,
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = 20,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device irda_device = {
+	.name           = "sh_sir",
+	.num_resources  = ARRAY_SIZE(irda_resources),
+	.resource       = irda_resources,
+};
+
 static struct platform_device *ms7724se_devices[] __initdata = {
 	&heartbeat_device,
 	&smc91x_eth_device,
@@ -512,6 +523,7 @@
 	&fsi_device,
 	&sdhi0_cn7_device,
 	&sdhi1_cn8_device,
+	&irda_device,
 };
 
 /* I2C device */
@@ -531,7 +543,7 @@
 	int t = 10000;
 
 	while (t--) {
-		if (!ctrl_inw(EEPROM_STAT))
+		if (!__raw_readw(EEPROM_STAT))
 			return 1;
 		udelay(1);
 	}
@@ -551,13 +563,13 @@
 
 	/* read MAC addr from EEPROM */
 	for (i = 0 ; i < 3 ; i++) {
-		ctrl_outw(0x0, EEPROM_OP); /* read */
-		ctrl_outw(i*2, EEPROM_ADR);
-		ctrl_outw(0x1, EEPROM_STRT);
+		__raw_writew(0x0, EEPROM_OP); /* read */
+		__raw_writew(i*2, EEPROM_ADR);
+		__raw_writew(0x1, EEPROM_STRT);
 		if (!sh_eth_is_eeprom_ready())
 			return;
 
-		mac = ctrl_inw(EEPROM_DATA);
+		mac = __raw_readw(EEPROM_DATA);
 		sh_eth_plat.mac_addr[i << 1] = mac & 0xff;
 		sh_eth_plat.mac_addr[(i << 1) + 1] = mac >> 8;
 	}
@@ -594,28 +606,29 @@
 
 static int __init devices_setup(void)
 {
-	u16 sw = ctrl_inw(SW4140); /* select camera, monitor */
-	struct clk *fsia_clk;
+	u16 sw = __raw_readw(SW4140); /* select camera, monitor */
+	struct clk *clk;
 
 	/* register board specific self-refresh code */
-	sh_mobile_register_self_refresh(SUSP_SH_STANDBY | SUSP_SH_SF,
+	sh_mobile_register_self_refresh(SUSP_SH_STANDBY | SUSP_SH_SF |
+					SUSP_SH_RSTANDBY,
 					&ms7724se_sdram_enter_start,
 					&ms7724se_sdram_enter_end,
 					&ms7724se_sdram_leave_start,
 					&ms7724se_sdram_leave_end);
 	/* Reset Release */
-	ctrl_outw(ctrl_inw(FPGA_OUT) &
+	__raw_writew(__raw_readw(FPGA_OUT) &
 		  ~((1 << 1)  | /* LAN */
 		    (1 << 6)  | /* VIDEO DAC */
 		    (1 << 7)  | /* AK4643 */
+		    (1 << 8)  | /* IrDA */
 		    (1 << 12) | /* USB0 */
 		    (1 << 14)), /* RMII */
 		  FPGA_OUT);
 
 	/* turn on USB clocks, use external clock */
-	ctrl_outw((ctrl_inw(PORT_MSELCRB) & ~0xc000) | 0x8000, PORT_MSELCRB);
+	__raw_writew((__raw_readw(PORT_MSELCRB) & ~0xc000) | 0x8000, PORT_MSELCRB);
 
-#ifdef CONFIG_PM
 	/* Let LED9 show STATUS2 */
 	gpio_request(GPIO_FN_STATUS2, NULL);
 
@@ -624,28 +637,12 @@
 
 	/* 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);
+	__raw_writew(0x0600, 0xa40501d4);
 
 	/* enable USB1 port */
-	ctrl_outw(0x0600, 0xa4050192);
+	__raw_writew(0x0600, 0xa4050192);
 
 	/* enable IRQ 0,1,2 */
 	gpio_request(GPIO_FN_INTC_IRQ0, NULL);
@@ -693,7 +690,7 @@
 	gpio_request(GPIO_FN_LCDVCPWC, NULL);
 	gpio_request(GPIO_FN_LCDRD,    NULL);
 	gpio_request(GPIO_FN_LCDLCLK,  NULL);
-	ctrl_outw((ctrl_inw(PORT_HIZA) & ~0x0001), PORT_HIZA);
+	__raw_writew((__raw_readw(PORT_HIZA) & ~0x0001), PORT_HIZA);
 
 	/* enable CEU0 */
 	gpio_request(GPIO_FN_VIO0_D15, NULL);
@@ -764,13 +761,18 @@
 	gpio_request(GPIO_FN_CLKAUDIOBO, NULL);
 	gpio_request(GPIO_FN_FSIIASD,    NULL);
 
+	/* set SPU2 clock to 83.4 MHz */
+	clk = clk_get(NULL, "spu_clk");
+	clk_set_rate(clk, clk_round_rate(clk, 83333333));
+	clk_put(clk);
+
 	/* change parent of FSI A */
-	fsia_clk = clk_get(NULL, "fsia_clk");
+	clk = clk_get(NULL, "fsia_clk");
 	clk_register(&fsimcka_clk);
-	clk_set_parent(fsia_clk, &fsimcka_clk);
-	clk_set_rate(fsia_clk, 11000);
+	clk_set_parent(clk, &fsimcka_clk);
+	clk_set_rate(clk, 11000);
 	clk_set_rate(&fsimcka_clk, 11000);
-	clk_put(fsia_clk);
+	clk_put(clk);
 
 	/* SDHI0 connected to cn7 */
 	gpio_request(GPIO_FN_SDHI0CD, NULL);
@@ -792,6 +794,10 @@
 	gpio_request(GPIO_FN_SDHI1CMD, NULL);
 	gpio_request(GPIO_FN_SDHI1CLK, NULL);
 
+	/* enable IrDA */
+	gpio_request(GPIO_FN_IRDA_OUT, NULL);
+	gpio_request(GPIO_FN_IRDA_IN,  NULL);
+
 	/*
 	 * enable SH-Eth
 	 *
diff --git a/arch/sh/boards/mach-se/7780/irq.c b/arch/sh/boards/mach-se/7780/irq.c
index 121744c..d5c9edc 100644
--- a/arch/sh/boards/mach-se/7780/irq.c
+++ b/arch/sh/boards/mach-se/7780/irq.c
@@ -24,30 +24,30 @@
 void __init init_se7780_IRQ(void)
 {
 	/* enable all interrupt at FPGA */
-	ctrl_outw(0, FPGA_INTMSK1);
+	__raw_writew(0, FPGA_INTMSK1);
 	/* mask SM501 interrupt */
-	ctrl_outw((ctrl_inw(FPGA_INTMSK1) | 0x0002), FPGA_INTMSK1);
+	__raw_writew((__raw_readw(FPGA_INTMSK1) | 0x0002), FPGA_INTMSK1);
 	/* enable all interrupt at FPGA */
-	ctrl_outw(0, FPGA_INTMSK2);
+	__raw_writew(0, FPGA_INTMSK2);
 
 	/* set FPGA INTSEL register */
 	/* FPGA + 0x06 */
-	ctrl_outw( ((IRQPIN_SM501 << IRQPOS_SM501) |
+	__raw_writew( ((IRQPIN_SM501 << IRQPOS_SM501) |
 		(IRQPIN_SMC91CX << IRQPOS_SMC91CX)), FPGA_INTSEL1);
 
 	/* FPGA + 0x08 */
-	ctrl_outw(((IRQPIN_EXTINT4 << IRQPOS_EXTINT4) |
+	__raw_writew(((IRQPIN_EXTINT4 << IRQPOS_EXTINT4) |
 		(IRQPIN_EXTINT3 << IRQPOS_EXTINT3) |
 		(IRQPIN_EXTINT2 << IRQPOS_EXTINT2) |
 		(IRQPIN_EXTINT1 << IRQPOS_EXTINT1)), FPGA_INTSEL2);
 
 	/* FPGA + 0x0A */
-	ctrl_outw((IRQPIN_PCCPW << IRQPOS_PCCPW), FPGA_INTSEL3);
+	__raw_writew((IRQPIN_PCCPW << IRQPOS_PCCPW), FPGA_INTSEL3);
 
 	plat_irq_setup_pins(IRQ_MODE_IRQ); /* install handlers for IRQ0-7 */
 
 	/* ICR1: detect low level(for 2ndcut) */
-	ctrl_outl(0xAAAA0000, INTC_ICR1);
+	__raw_writel(0xAAAA0000, INTC_ICR1);
 
 	/*
 	 * FPGA PCISEL register initialize
@@ -63,6 +63,6 @@
 	 *  INTD || INTD  | INTC  |  --   | INTA
 	 *  -------------------------------------
 	 */
-	ctrl_outw(0x0013, FPGA_PCI_INTSEL1);
-	ctrl_outw(0xE402, FPGA_PCI_INTSEL2);
+	__raw_writew(0x0013, FPGA_PCI_INTSEL1);
+	__raw_writew(0xE402, FPGA_PCI_INTSEL2);
 }
diff --git a/arch/sh/boards/mach-se/7780/setup.c b/arch/sh/boards/mach-se/7780/setup.c
index 1d3a867..6f7c207 100644
--- a/arch/sh/boards/mach-se/7780/setup.c
+++ b/arch/sh/boards/mach-se/7780/setup.c
@@ -17,26 +17,17 @@
 #include <asm/heartbeat.h>
 
 /* Heartbeat */
-static struct heartbeat_data heartbeat_data = {
-	.regsize = 16,
-};
-
-static struct resource heartbeat_resources[] = {
-	[0] = {
-		.start  = PA_LED,
-		.end    = PA_LED,
-		.flags  = IORESOURCE_MEM,
-	},
+static struct resource heartbeat_resource = {
+	.start  = PA_LED,
+	.end    = PA_LED,
+	.flags  = IORESOURCE_MEM | IORESOURCE_MEM_16BIT,
 };
 
 static struct platform_device heartbeat_device = {
 	.name           = "heartbeat",
 	.id             = -1,
-	.dev = {
-		.platform_data = &heartbeat_data,
-	},
-	.num_resources  = ARRAY_SIZE(heartbeat_resources),
-	.resource       = heartbeat_resources,
+	.num_resources  = 1,
+	.resource       = &heartbeat_resource,
 };
 
 /* SMC91x */
@@ -84,14 +75,14 @@
 static void __init se7780_setup(char **cmdline_p)
 {
 	/* "SH-Linux" on LED Display */
-	ctrl_outw( 'S' , PA_LED_DISP + (DISP_SEL0_ADDR << 1) );
-	ctrl_outw( 'H' , PA_LED_DISP + (DISP_SEL1_ADDR << 1) );
-	ctrl_outw( '-' , PA_LED_DISP + (DISP_SEL2_ADDR << 1) );
-	ctrl_outw( 'L' , PA_LED_DISP + (DISP_SEL3_ADDR << 1) );
-	ctrl_outw( 'i' , PA_LED_DISP + (DISP_SEL4_ADDR << 1) );
-	ctrl_outw( 'n' , PA_LED_DISP + (DISP_SEL5_ADDR << 1) );
-	ctrl_outw( 'u' , PA_LED_DISP + (DISP_SEL6_ADDR << 1) );
-	ctrl_outw( 'x' , PA_LED_DISP + (DISP_SEL7_ADDR << 1) );
+	__raw_writew( 'S' , PA_LED_DISP + (DISP_SEL0_ADDR << 1) );
+	__raw_writew( 'H' , PA_LED_DISP + (DISP_SEL1_ADDR << 1) );
+	__raw_writew( '-' , PA_LED_DISP + (DISP_SEL2_ADDR << 1) );
+	__raw_writew( 'L' , PA_LED_DISP + (DISP_SEL3_ADDR << 1) );
+	__raw_writew( 'i' , PA_LED_DISP + (DISP_SEL4_ADDR << 1) );
+	__raw_writew( 'n' , PA_LED_DISP + (DISP_SEL5_ADDR << 1) );
+	__raw_writew( 'u' , PA_LED_DISP + (DISP_SEL6_ADDR << 1) );
+	__raw_writew( 'x' , PA_LED_DISP + (DISP_SEL7_ADDR << 1) );
 
 	printk(KERN_INFO "Hitachi UL Solutions Engine 7780SE03 support.\n");
 
@@ -102,15 +93,15 @@
 	 *   REQ2/GNT2 -> Serial ATA
 	 *   REQ3/GNT3 -> PCI slot
 	 */
-	ctrl_outw(0x0213, FPGA_REQSEL);
+	__raw_writew(0x0213, FPGA_REQSEL);
 
 	/* GPIO setting */
-	ctrl_outw(0x0000, GPIO_PECR);
-	ctrl_outw(ctrl_inw(GPIO_PHCR)&0xfff3, GPIO_PHCR);
-	ctrl_outw(0x0c00, GPIO_PMSELR);
+	__raw_writew(0x0000, GPIO_PECR);
+	__raw_writew(__raw_readw(GPIO_PHCR)&0xfff3, GPIO_PHCR);
+	__raw_writew(0x0c00, GPIO_PMSELR);
 
 	/* iVDR Power ON */
-	ctrl_outw(0x0001, FPGA_IVDRPW);
+	__raw_writew(0x0001, FPGA_IVDRPW);
 }
 
 /*
diff --git a/arch/sh/boards/mach-sh03/rtc.c b/arch/sh/boards/mach-sh03/rtc.c
index a8b9f84..1b20099 100644
--- a/arch/sh/boards/mach-sh03/rtc.c
+++ b/arch/sh/boards/mach-sh03/rtc.c
@@ -44,15 +44,15 @@
 	spin_lock(&sh03_rtc_lock);
  again:
 	do {
-		sec  = (ctrl_inb(RTC_SEC1) & 0xf) + (ctrl_inb(RTC_SEC10) & 0x7) * 10;
-		min  = (ctrl_inb(RTC_MIN1) & 0xf) + (ctrl_inb(RTC_MIN10) & 0xf) * 10;
-		hour = (ctrl_inb(RTC_HOU1) & 0xf) + (ctrl_inb(RTC_HOU10) & 0xf) * 10;
-		day  = (ctrl_inb(RTC_DAY1) & 0xf) + (ctrl_inb(RTC_DAY10) & 0xf) * 10;
-		mon  = (ctrl_inb(RTC_MON1) & 0xf) + (ctrl_inb(RTC_MON10) & 0xf) * 10;
-		year = (ctrl_inb(RTC_YEA1) & 0xf) + (ctrl_inb(RTC_YEA10) & 0xf) * 10
-		     + (ctrl_inb(RTC_YEA100 ) & 0xf) * 100
-		     + (ctrl_inb(RTC_YEA1000) & 0xf) * 1000;
-	} while (sec != (ctrl_inb(RTC_SEC1) & 0xf) + (ctrl_inb(RTC_SEC10) & 0x7) * 10);
+		sec  = (__raw_readb(RTC_SEC1) & 0xf) + (__raw_readb(RTC_SEC10) & 0x7) * 10;
+		min  = (__raw_readb(RTC_MIN1) & 0xf) + (__raw_readb(RTC_MIN10) & 0xf) * 10;
+		hour = (__raw_readb(RTC_HOU1) & 0xf) + (__raw_readb(RTC_HOU10) & 0xf) * 10;
+		day  = (__raw_readb(RTC_DAY1) & 0xf) + (__raw_readb(RTC_DAY10) & 0xf) * 10;
+		mon  = (__raw_readb(RTC_MON1) & 0xf) + (__raw_readb(RTC_MON10) & 0xf) * 10;
+		year = (__raw_readb(RTC_YEA1) & 0xf) + (__raw_readb(RTC_YEA10) & 0xf) * 10
+		     + (__raw_readb(RTC_YEA100 ) & 0xf) * 100
+		     + (__raw_readb(RTC_YEA1000) & 0xf) * 1000;
+	} while (sec != (__raw_readb(RTC_SEC1) & 0xf) + (__raw_readb(RTC_SEC10) & 0x7) * 10);
 	if (year == 0 || mon < 1 || mon > 12 || day > 31 || day < 1 ||
 	    hour > 23 || min > 59 || sec > 59) {
 		printk(KERN_ERR
@@ -60,16 +60,16 @@
 		printk("year=%d, mon=%d, day=%d, hour=%d, min=%d, sec=%d\n",
 		       year, mon, day, hour, min, sec);
 
-		ctrl_outb(0, RTC_SEC1); ctrl_outb(0, RTC_SEC10);
-		ctrl_outb(0, RTC_MIN1); ctrl_outb(0, RTC_MIN10);
-		ctrl_outb(0, RTC_HOU1); ctrl_outb(0, RTC_HOU10);
-		ctrl_outb(6, RTC_WEE1);
-		ctrl_outb(1, RTC_DAY1); ctrl_outb(0, RTC_DAY10);
-		ctrl_outb(1, RTC_MON1); ctrl_outb(0, RTC_MON10);
-		ctrl_outb(0, RTC_YEA1); ctrl_outb(0, RTC_YEA10);
-		ctrl_outb(0, RTC_YEA100);
-		ctrl_outb(2, RTC_YEA1000);
-		ctrl_outb(0, RTC_CTL);
+		__raw_writeb(0, RTC_SEC1); __raw_writeb(0, RTC_SEC10);
+		__raw_writeb(0, RTC_MIN1); __raw_writeb(0, RTC_MIN10);
+		__raw_writeb(0, RTC_HOU1); __raw_writeb(0, RTC_HOU10);
+		__raw_writeb(6, RTC_WEE1);
+		__raw_writeb(1, RTC_DAY1); __raw_writeb(0, RTC_DAY10);
+		__raw_writeb(1, RTC_MON1); __raw_writeb(0, RTC_MON10);
+		__raw_writeb(0, RTC_YEA1); __raw_writeb(0, RTC_YEA10);
+		__raw_writeb(0, RTC_YEA100);
+		__raw_writeb(2, RTC_YEA1000);
+		__raw_writeb(0, RTC_CTL);
 		goto again;
 	}
 
@@ -93,9 +93,9 @@
 	/* gets recalled with irq locally disabled */
 	spin_lock(&sh03_rtc_lock);
 	for (i = 0 ; i < 1000000 ; i++)	/* may take up to 1 second... */
-		if (!(ctrl_inb(RTC_CTL) & RTC_BUSY))
+		if (!(__raw_readb(RTC_CTL) & RTC_BUSY))
 			break;
-	cmos_minutes = (ctrl_inb(RTC_MIN1) & 0xf) + (ctrl_inb(RTC_MIN10) & 0xf) * 10;
+	cmos_minutes = (__raw_readb(RTC_MIN1) & 0xf) + (__raw_readb(RTC_MIN10) & 0xf) * 10;
 	real_seconds = nowtime % 60;
 	real_minutes = nowtime / 60;
 	if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
@@ -103,10 +103,10 @@
 	real_minutes %= 60;
 
 	if (abs(real_minutes - cmos_minutes) < 30) {
-		ctrl_outb(real_seconds % 10, RTC_SEC1);
-		ctrl_outb(real_seconds / 10, RTC_SEC10);
-		ctrl_outb(real_minutes % 10, RTC_MIN1);
-		ctrl_outb(real_minutes / 10, RTC_MIN10);
+		__raw_writeb(real_seconds % 10, RTC_SEC1);
+		__raw_writeb(real_seconds / 10, RTC_SEC10);
+		__raw_writeb(real_minutes % 10, RTC_MIN1);
+		__raw_writeb(real_minutes / 10, RTC_MIN10);
 	} else {
 		printk(KERN_WARNING
 		       "set_rtc_mmss: can't update from %d to %d\n",
diff --git a/arch/sh/boards/mach-sh03/setup.c b/arch/sh/boards/mach-sh03/setup.c
index 74cfb4b..af4a0c0 100644
--- a/arch/sh/boards/mach-sh03/setup.c
+++ b/arch/sh/boards/mach-sh03/setup.c
@@ -82,7 +82,7 @@
 	/* open I/O area window */
 	paddrbase = virt_to_phys((void *)PA_AREA5_IO);
 	prot = PAGE_KERNEL_PCC(1, _PAGE_PCC_IO16);
-	cf_ide_base = p3_ioremap(paddrbase, PAGE_SIZE, prot.pgprot);
+	cf_ide_base = ioremap_prot(paddrbase, PAGE_SIZE, pgprot_val(prot));
 	if (!cf_ide_base) {
 		printk("allocate_cf_area : can't open CF I/O window!\n");
 		return -ENOMEM;
diff --git a/arch/sh/boards/mach-sh7763rdp/irq.c b/arch/sh/boards/mach-sh7763rdp/irq.c
index d8ebfa7..add698c 100644
--- a/arch/sh/boards/mach-sh7763rdp/irq.c
+++ b/arch/sh/boards/mach-sh7763rdp/irq.c
@@ -28,18 +28,18 @@
 void __init init_sh7763rdp_IRQ(void)
 {
 	/* GPIO enabled */
-	ctrl_outl(1 << 25, INTC_INT2MSKCR);
+	__raw_writel(1 << 25, INTC_INT2MSKCR);
 
 	/* enable GPIO interrupts */
-	ctrl_outl((ctrl_inl(INTC_INT2PRI7) & 0xFF00FFFF) | 0x000F0000,
+	__raw_writel((__raw_readl(INTC_INT2PRI7) & 0xFF00FFFF) | 0x000F0000,
 		  INTC_INT2PRI7);
 
 	/* USBH enabled */
-	ctrl_outl(1 << 17, INTC_INT2MSKCR1);
+	__raw_writel(1 << 17, INTC_INT2MSKCR1);
 
 	/* GETHER enabled */
-	ctrl_outl(1 << 16, INTC_INT2MSKCR1);
+	__raw_writel(1 << 16, INTC_INT2MSKCR1);
 
 	/* DMAC enabled */
-	ctrl_outl(1 << 8, INTC_INT2MSKCR);
+	__raw_writel(1 << 8, INTC_INT2MSKCR);
 }
diff --git a/arch/sh/boards/mach-sh7763rdp/setup.c b/arch/sh/boards/mach-sh7763rdp/setup.c
index 390534a..f64a691 100644
--- a/arch/sh/boards/mach-sh7763rdp/setup.c
+++ b/arch/sh/boards/mach-sh7763rdp/setup.c
@@ -158,50 +158,50 @@
 static void __init sh7763rdp_setup(char **cmdline_p)
 {
 	/* Board version check */
-	if (ctrl_inw(CPLD_BOARD_ID_ERV_REG) == 0xECB1)
+	if (__raw_readw(CPLD_BOARD_ID_ERV_REG) == 0xECB1)
 		printk(KERN_INFO "RTE Standard Configuration\n");
 	else
 		printk(KERN_INFO "RTA Standard Configuration\n");
 
 	/* USB pin select bits (clear bit 5-2 to 0) */
-	ctrl_outw((ctrl_inw(PORT_PSEL2) & 0xFFC3), PORT_PSEL2);
+	__raw_writew((__raw_readw(PORT_PSEL2) & 0xFFC3), PORT_PSEL2);
 	/* USBH setup port I controls to other (clear bits 4-9 to 0) */
-	ctrl_outw(ctrl_inw(PORT_PICR) & 0xFC0F, PORT_PICR);
+	__raw_writew(__raw_readw(PORT_PICR) & 0xFC0F, PORT_PICR);
 
 	/* Select USB Host controller */
-	ctrl_outw(0x00, USB_USBHSC);
+	__raw_writew(0x00, USB_USBHSC);
 
 	/* For LCD */
 	/* set PTJ7-1, bits 15-2 of PJCR to 0 */
-	ctrl_outw(ctrl_inw(PORT_PJCR) & 0x0003, PORT_PJCR);
+	__raw_writew(__raw_readw(PORT_PJCR) & 0x0003, PORT_PJCR);
 	/* set PTI5, bits 11-10 of PICR to 0 */
-	ctrl_outw(ctrl_inw(PORT_PICR) & 0xF3FF, PORT_PICR);
-	ctrl_outw(0, PORT_PKCR);
-	ctrl_outw(0, PORT_PLCR);
+	__raw_writew(__raw_readw(PORT_PICR) & 0xF3FF, PORT_PICR);
+	__raw_writew(0, PORT_PKCR);
+	__raw_writew(0, PORT_PLCR);
 	/* set PSEL2 bits 14-8, 5-4, of PSEL2 to 0 */
-	ctrl_outw((ctrl_inw(PORT_PSEL2) & 0x00C0), PORT_PSEL2);
+	__raw_writew((__raw_readw(PORT_PSEL2) & 0x00C0), PORT_PSEL2);
 	/* set PSEL3 bits 14-12, 6-4, 2-0 of PSEL3 to 0 */
-	ctrl_outw((ctrl_inw(PORT_PSEL3) & 0x0700), PORT_PSEL3);
+	__raw_writew((__raw_readw(PORT_PSEL3) & 0x0700), PORT_PSEL3);
 
 	/* For HAC */
 	/* bit3-0  0100:HAC & SSI1 enable */
-	ctrl_outw((ctrl_inw(PORT_PSEL1) & 0xFFF0) | 0x0004, PORT_PSEL1);
+	__raw_writew((__raw_readw(PORT_PSEL1) & 0xFFF0) | 0x0004, PORT_PSEL1);
 	/* bit14      1:SSI_HAC_CLK enable */
-	ctrl_outw(ctrl_inw(PORT_PSEL4) | 0x4000, PORT_PSEL4);
+	__raw_writew(__raw_readw(PORT_PSEL4) | 0x4000, PORT_PSEL4);
 
 	/* SH-Ether */
-	ctrl_outw((ctrl_inw(PORT_PSEL1) & ~0xff00) | 0x2400, PORT_PSEL1);
-	ctrl_outw(0x0, PORT_PFCR);
-	ctrl_outw(0x0, PORT_PFCR);
-	ctrl_outw(0x0, PORT_PFCR);
+	__raw_writew((__raw_readw(PORT_PSEL1) & ~0xff00) | 0x2400, PORT_PSEL1);
+	__raw_writew(0x0, PORT_PFCR);
+	__raw_writew(0x0, PORT_PFCR);
+	__raw_writew(0x0, PORT_PFCR);
 
 	/* MMC */
 	/*selects SCIF and MMC other functions */
-	ctrl_outw(0x0001, PORT_PSEL0);
+	__raw_writew(0x0001, PORT_PSEL0);
 	/* MMC clock operates */
-	ctrl_outl(ctrl_inl(MSTPCR1) & ~0x8, MSTPCR1);
-	ctrl_outw(ctrl_inw(PORT_PACR) & ~0x3000, PORT_PACR);
-	ctrl_outw(ctrl_inw(PORT_PCCR) & ~0xCFC3, PORT_PCCR);
+	__raw_writel(__raw_readl(MSTPCR1) & ~0x8, MSTPCR1);
+	__raw_writew(__raw_readw(PORT_PACR) & ~0x3000, PORT_PACR);
+	__raw_writew(__raw_readw(PORT_PCCR) & ~0xCFC3, PORT_PCCR);
 }
 
 static struct sh_machine_vector mv_sh7763rdp __initmv = {
diff --git a/arch/sh/boards/mach-snapgear/setup.c b/arch/sh/boards/mach-snapgear/setup.c
index a3277a2..331745d 100644
--- a/arch/sh/boards/mach-snapgear/setup.c
+++ b/arch/sh/boards/mach-snapgear/setup.c
@@ -30,7 +30,7 @@
 
 static irqreturn_t eraseconfig_interrupt(int irq, void *dev_id)
 {
-	(void)ctrl_inb(0xb8000000);	/* dummy read */
+	(void)__raw_readb(0xb8000000);	/* dummy read */
 
 	printk("SnapGear: erase switch interrupt!\n");
 
diff --git a/arch/sh/boards/mach-systemh/irq.c b/arch/sh/boards/mach-systemh/irq.c
index 986a0e7..523aea5 100644
--- a/arch/sh/boards/mach-systemh/irq.c
+++ b/arch/sh/boards/mach-systemh/irq.c
@@ -41,13 +41,13 @@
 		unsigned long val, mask = 0x01 << 1;
 
 		/* Clear the "irq"th bit in the mask and set it in the request */
-		val = ctrl_inl((unsigned long)systemh_irq_mask_register);
+		val = __raw_readl((unsigned long)systemh_irq_mask_register);
 		val &= ~mask;
-		ctrl_outl(val, (unsigned long)systemh_irq_mask_register);
+		__raw_writel(val, (unsigned long)systemh_irq_mask_register);
 
-		val = ctrl_inl((unsigned long)systemh_irq_request_register);
+		val = __raw_readl((unsigned long)systemh_irq_request_register);
 		val |= mask;
-		ctrl_outl(val, (unsigned long)systemh_irq_request_register);
+		__raw_writel(val, (unsigned long)systemh_irq_request_register);
 	}
 }
 
@@ -57,9 +57,9 @@
 		unsigned long val, mask = 0x01 << 1;
 
 		/* Set "irq"th bit in the mask register */
-		val = ctrl_inl((unsigned long)systemh_irq_mask_register);
+		val = __raw_readl((unsigned long)systemh_irq_mask_register);
 		val |= mask;
-		ctrl_outl(val, (unsigned long)systemh_irq_mask_register);
+		__raw_writel(val, (unsigned long)systemh_irq_mask_register);
 	}
 }
 
diff --git a/arch/sh/boards/mach-titan/Makefile b/arch/sh/boards/mach-titan/Makefile
deleted file mode 100644
index 08d7537..0000000
--- a/arch/sh/boards/mach-titan/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-#
-# Makefile for the Nimble Microsystems TITAN specific parts of the kernel
-#
-
-obj-y	 := setup.o io.o
diff --git a/arch/sh/boards/mach-titan/io.c b/arch/sh/boards/mach-titan/io.c
deleted file mode 100644
index 0130e98..0000000
--- a/arch/sh/boards/mach-titan/io.c
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- *	I/O routines for Titan
- */
-#include <linux/pci.h>
-#include <asm/machvec.h>
-#include <asm/addrspace.h>
-#include <mach/titan.h>
-#include <asm/io.h>
-
-static inline unsigned int port2adr(unsigned int port)
-{
-        maybebadio((unsigned long)port);
-        return port;
-}
-
-u8 titan_inb(unsigned long port)
-{
-        if (PXSEG(port))
-                return ctrl_inb(port);
-        return ctrl_inw(port2adr(port)) & 0xff;
-}
-
-u8 titan_inb_p(unsigned long port)
-{
-        u8 v;
-
-        if (PXSEG(port))
-                v = ctrl_inb(port);
-        else
-                v = ctrl_inw(port2adr(port)) & 0xff;
-        ctrl_delay();
-        return v;
-}
-
-u16 titan_inw(unsigned long port)
-{
-        if (PXSEG(port))
-                return ctrl_inw(port);
-        else if (port >= 0x2000)
-                return ctrl_inw(port2adr(port));
-        else
-                maybebadio(port);
-        return 0;
-}
-
-u32 titan_inl(unsigned long port)
-{
-        if (PXSEG(port))
-                return ctrl_inl(port);
-        else if (port >= 0x2000)
-                return ctrl_inw(port2adr(port));
-        else
-                maybebadio(port);
-        return 0;
-}
-
-void titan_outb(u8 value, unsigned long port)
-{
-        if (PXSEG(port))
-                ctrl_outb(value, port);
-        else
-                ctrl_outw(value, port2adr(port));
-}
-
-void titan_outb_p(u8 value, unsigned long port)
-{
-        if (PXSEG(port))
-                ctrl_outb(value, port);
-        else
-                ctrl_outw(value, port2adr(port));
-        ctrl_delay();
-}
-
-void titan_outw(u16 value, unsigned long port)
-{
-        if (PXSEG(port))
-                ctrl_outw(value, port);
-        else if (port >= 0x2000)
-                ctrl_outw(value, port2adr(port));
-        else
-                maybebadio(port);
-}
-
-void titan_outl(u32 value, unsigned long port)
-{
-        if (PXSEG(port))
-                ctrl_outl(value, port);
-        else
-                maybebadio(port);
-}
-
-void titan_insl(unsigned long port, void *dst, unsigned long count)
-{
-        maybebadio(port);
-}
-
-void titan_outsl(unsigned long port, const void *src, unsigned long count)
-{
-        maybebadio(port);
-}
-
-void __iomem *titan_ioport_map(unsigned long port, unsigned int size)
-{
-	if (PXSEG(port))
-		return (void __iomem *)port;
-
-	return (void __iomem *)port2adr(port);
-}
diff --git a/arch/sh/boards/mach-titan/setup.c b/arch/sh/boards/mach-titan/setup.c
deleted file mode 100644
index 81e7e0f..0000000
--- a/arch/sh/boards/mach-titan/setup.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * arch/sh/boards/titan/setup.c - Setup for Titan
- *
- *  Copyright (C) 2006  Jamie Lenehan
- *
- * 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/irq.h>
-#include <mach/titan.h>
-#include <asm/io.h>
-
-static void __init init_titan_irq(void)
-{
-	/* enable individual interrupt mode for externals */
-	plat_irq_setup_pins(IRQ_MODE_IRQ);
-}
-
-static struct sh_machine_vector mv_titan __initmv = {
-	.mv_name =	"Titan",
-
-	.mv_inb =	titan_inb,
-	.mv_inw =	titan_inw,
-	.mv_inl =	titan_inl,
-	.mv_outb =	titan_outb,
-	.mv_outw =	titan_outw,
-	.mv_outl =	titan_outl,
-
-	.mv_inb_p =	titan_inb_p,
-	.mv_inw_p =	titan_inw,
-	.mv_inl_p =	titan_inl,
-	.mv_outb_p =	titan_outb_p,
-	.mv_outw_p =	titan_outw,
-	.mv_outl_p =	titan_outl,
-
-	.mv_insl =	titan_insl,
-	.mv_outsl =	titan_outsl,
-
-	.mv_ioport_map = titan_ioport_map,
-
-	.mv_init_irq =	init_titan_irq,
-};
diff --git a/arch/sh/boards/mach-x3proto/ilsel.c b/arch/sh/boards/mach-x3proto/ilsel.c
index b5c673c..5c98427 100644
--- a/arch/sh/boards/mach-x3proto/ilsel.c
+++ b/arch/sh/boards/mach-x3proto/ilsel.c
@@ -70,10 +70,10 @@
 	pr_debug("%s: bit#%d: addr - 0x%08lx (shift %d, set %d)\n",
 		 __func__, bit, addr, shift, set);
 
-	tmp = ctrl_inw(addr);
+	tmp = __raw_readw(addr);
 	tmp &= ~(0xf << shift);
 	tmp |= set << shift;
-	ctrl_outw(tmp, addr);
+	__raw_writew(tmp, addr);
 }
 
 /**
@@ -142,9 +142,9 @@
 
 	addr = mk_ilsel_addr(irq);
 
-	tmp = ctrl_inw(addr);
+	tmp = __raw_readw(addr);
 	tmp &= ~(0xf << mk_ilsel_shift(irq));
-	ctrl_outw(tmp, addr);
+	__raw_writew(tmp, addr);
 
 	clear_bit(irq, &ilsel_level_map);
 }
diff --git a/arch/sh/boards/mach-x3proto/setup.c b/arch/sh/boards/mach-x3proto/setup.c
index efe4cb9..e284592 100644
--- a/arch/sh/boards/mach-x3proto/setup.c
+++ b/arch/sh/boards/mach-x3proto/setup.c
@@ -149,7 +149,7 @@
 	plat_irq_setup_pins(IRQ_MODE_IRL3210);
 
 	/* Set ICR0.LVLMODE */
-	ctrl_outl(ctrl_inl(0xfe410000) | (1 << 21), 0xfe410000);
+	__raw_writel(__raw_readl(0xfe410000) | (1 << 21), 0xfe410000);
 }
 
 static struct sh_machine_vector mv_x3proto __initmv = {
diff --git a/arch/sh/boot/Makefile b/arch/sh/boot/Makefile
index cb8cf55..1ce6362 100644
--- a/arch/sh/boot/Makefile
+++ b/arch/sh/boot/Makefile
@@ -21,12 +21,15 @@
 CONFIG_ENTRY_OFFSET	?= 0x00001000
 
 suffix-y := bin
-suffix-$(CONFIG_KERNEL_GZIP)  := gz
-suffix-$(CONFIG_KERNEL_BZIP2) := bz2
-suffix-$(CONFIG_KERNEL_LZMA)  := lzma
+suffix-$(CONFIG_KERNEL_GZIP)	:= gz
+suffix-$(CONFIG_KERNEL_BZIP2)	:= bz2
+suffix-$(CONFIG_KERNEL_LZMA)	:= lzma
+suffix-$(CONFIG_KERNEL_LZO)	:= lzo
 
-targets := zImage vmlinux.srec romImage uImage uImage.srec uImage.gz uImage.bz2 uImage.lzma uImage.bin
-extra-y += vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma
+targets := zImage vmlinux.srec romImage uImage uImage.srec uImage.gz \
+	   uImage.bz2 uImage.lzma uImage.lzo uImage.bin
+extra-y += vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma \
+	   vmlinux.bin.lzo
 subdir- := compressed romimage
 
 $(obj)/zImage: $(obj)/compressed/vmlinux FORCE
@@ -43,15 +46,8 @@
 $(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" \
+KERNEL_MEMORY	:= $(shell /bin/bash -c 'printf "0x%08x" \
 		     $$[$(CONFIG_MEMORY_START) & 0x1fffffff]')
-endif
-ifeq ($(CONFIG_29BIT),y)
-KERNEL_MEMORY := $(shell /bin/bash -c 'printf "0x%08x" \
-		     $$[$(CONFIG_MEMORY_START)]')
-endif
 
 KERNEL_LOAD	:= $(shell /bin/bash -c 'printf "0x%08x" \
 		     $$[$(CONFIG_PAGE_OFFSET)  + \
@@ -80,6 +76,9 @@
 $(obj)/vmlinux.bin.lzma: $(obj)/vmlinux.bin FORCE
 	$(call if_changed,lzma)
 
+$(obj)/vmlinux.bin.lzo: $(obj)/vmlinux.bin FORCE
+	$(call if_changed,lzo)
+
 $(obj)/uImage.bz2: $(obj)/vmlinux.bin.bz2
 	$(call if_changed,uimage,bzip2)
 
@@ -89,6 +88,9 @@
 $(obj)/uImage.lzma: $(obj)/vmlinux.bin.lzma
 	$(call if_changed,uimage,lzma)
 
+$(obj)/uImage.lzo: $(obj)/vmlinux.bin.lzo
+	$(call if_changed,uimage,lzo)
+
 $(obj)/uImage.bin: $(obj)/vmlinux.bin
 	$(call if_changed,uimage,none)
 
diff --git a/arch/sh/boot/compressed/Makefile b/arch/sh/boot/compressed/Makefile
index 6182eca..5d660b9 100644
--- a/arch/sh/boot/compressed/Makefile
+++ b/arch/sh/boot/compressed/Makefile
@@ -6,14 +6,11 @@
 
 targets		:= vmlinux vmlinux.bin vmlinux.bin.gz \
 		   vmlinux.bin.bz2 vmlinux.bin.lzma \
+		   vmlinux.bin.lzo \
 		   head_$(BITS).o misc.o piggy.o
 
 OBJECTS = $(obj)/head_$(BITS).o $(obj)/misc.o $(obj)/cache.o
 
-ifdef CONFIG_SH_STANDARD_BIOS
-OBJECTS += $(obj)/../../kernel/sh_bios.o
-endif
-
 #
 # IMAGE_OFFSET is the load offset of the compression loader
 #
@@ -47,6 +44,8 @@
 	$(call if_changed,bzip2)
 $(obj)/vmlinux.bin.lzma: $(vmlinux.bin.all-y) FORCE
 	$(call if_changed,lzma)
+$(obj)/vmlinux.bin.lzo: $(vmlinux.bin.all-y) FORCE
+	$(call if_changed,lzo)
 
 OBJCOPYFLAGS += -R .empty_zero_page
 
diff --git a/arch/sh/boot/compressed/misc.c b/arch/sh/boot/compressed/misc.c
index b51b1fc..27140a6 100644
--- a/arch/sh/boot/compressed/misc.c
+++ b/arch/sh/boot/compressed/misc.c
@@ -14,7 +14,6 @@
 #include <asm/uaccess.h>
 #include <asm/addrspace.h>
 #include <asm/page.h>
-#include <asm/sh_bios.h>
 
 /*
  * gzip declarations
@@ -62,29 +61,15 @@
 #include "../../../../lib/decompress_unlzma.c"
 #endif
 
-#ifdef CONFIG_SH_STANDARD_BIOS
-size_t strlen(const char *s)
-{
-	int i = 0;
+#ifdef CONFIG_KERNEL_LZO
+#include "../../../../lib/decompress_unlzo.c"
+#endif
 
-	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)
 {
@@ -132,7 +117,7 @@
 	output_addr = (CONFIG_MEMORY_START + 0x2000);
 #else
 	output_addr = __pa((unsigned long)&_text+PAGE_SIZE);
-#ifdef CONFIG_29BIT
+#if defined(CONFIG_29BIT)
 	output_addr |= P2SEG;
 #endif
 #endif
diff --git a/arch/sh/cchips/hd6446x/hd64461.c b/arch/sh/cchips/hd6446x/hd64461.c
index 50aa0c1..bcb31ae8 100644
--- a/arch/sh/cchips/hd6446x/hd64461.c
+++ b/arch/sh/cchips/hd6446x/hd64461.c
@@ -55,25 +55,22 @@
 
 static void hd64461_irq_demux(unsigned int irq, struct irq_desc *desc)
 {
-	unsigned short intv = ctrl_inw(HD64461_NIRR);
-	struct irq_desc *ext_desc;
+	unsigned short intv = __raw_readw(HD64461_NIRR);
 	unsigned int ext_irq = HD64461_IRQBASE;
 
 	intv &= (1 << HD64461_IRQ_NUM) - 1;
 
-	while (intv) {
-		if (intv & 1) {
-			ext_desc = irq_desc + ext_irq;
-			handle_level_irq(ext_irq, ext_desc);
-		}
-		intv >>= 1;
-		ext_irq++;
+	for (; intv; intv >>= 1, ext_irq++) {
+		if (!(intv & 1))
+			continue;
+
+		generic_handle_irq(ext_irq);
 	}
 }
 
 int __init setup_hd64461(void)
 {
-	int i;
+	int i, nid = cpu_to_node(boot_cpu_data);
 
 	if (!MACH_HD64461)
 		return 0;
@@ -90,9 +87,26 @@
 	__raw_writew(0xffff, HD64461_NIMR);
 
 	/*  IRQ 80 -> 95 belongs to HD64461  */
-	for (i = HD64461_IRQBASE; i < HD64461_IRQBASE + 16; i++)
+	for (i = HD64461_IRQBASE; i < HD64461_IRQBASE + 16; i++) {
+		unsigned int irq;
+
+		irq = create_irq_nr(i, nid);
+		if (unlikely(irq == 0)) {
+			pr_err("%s: failed hooking irq %d for HD64461\n",
+			       __func__, i);
+			return -EBUSY;
+		}
+
+		if (unlikely(irq != i)) {
+			pr_err("%s: got irq %d but wanted %d, bailing.\n",
+			       __func__, irq, i);
+			destroy_irq(irq);
+			return -EINVAL;
+		}
+
 		set_irq_chip_and_handler(i, &hd64461_irq_chip,
 					 handle_level_irq);
+	}
 
 	set_irq_chained_handler(CONFIG_HD64461_IRQ, hd64461_irq_demux);
 	set_irq_type(CONFIG_HD64461_IRQ, IRQ_TYPE_LEVEL_LOW);
diff --git a/arch/sh/configs/sdk7786_defconfig b/arch/sh/configs/sdk7786_defconfig
new file mode 100644
index 0000000..9b331ea
--- /dev/null
+++ b/arch/sh/configs/sdk7786_defconfig
@@ -0,0 +1,1754 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.33-rc7
+# Tue Feb  9 15:27:06 2010
+#
+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_IRQ_PER_CPU=y
+CONFIG_SPARSE_IRQ=y
+# CONFIG_GENERIC_GPIO is not set
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_ARCH_SUSPEND_POSSIBLE is not set
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_SYS_SUPPORTS_HUGETLBFS=y
+CONFIG_SYS_SUPPORTS_SMP=y
+CONFIG_SYS_SUPPORTS_NUMA=y
+CONFIG_SYS_SUPPORTS_PCI=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_DMA_COHERENT=y
+# CONFIG_DMA_NONCOHERENT is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_BZIP2=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_LZO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+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_TREE_RCU=y
+# CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_TINY_RCU is not set
+CONFIG_RCU_TRACE=y
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
+CONFIG_TREE_RCU_TRACE=y
+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=y
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+CONFIG_CGROUPS=y
+# CONFIG_CGROUP_DEBUG is not set
+CONFIG_CGROUP_NS=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_DEVICE=y
+# CONFIG_CPUSETS is not set
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
+CONFIG_CGROUP_MEM_RES_CTLR=y
+# CONFIG_CGROUP_MEM_RES_CTLR_SWAP is not set
+CONFIG_MM_OWNER=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+# CONFIG_RELAY is not set
+CONFIG_NAMESPACES=y
+CONFIG_UTS_NS=y
+CONFIG_IPC_NS=y
+CONFIG_USER_NS=y
+CONFIG_PID_NS=y
+CONFIG_NET_NS=y
+# CONFIG_BLK_DEV_INITRD 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=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_EXTRA_PASS 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_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_PERF_EVENTS=y
+CONFIG_EVENT_PROFILE=y
+# CONFIG_PERF_COUNTERS is not set
+# CONFIG_DEBUG_PERF_USE_VMALLOC is not set
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
+# CONFIG_OPROFILE is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_ATTRS=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_HW_BREAKPOINT=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=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+CONFIG_BLK_CGROUP=y
+# CONFIG_DEBUG_BLK_CGROUP is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_CFQ_GROUP_IOSCHED=y
+# CONFIG_DEBUG_CFQ_IOSCHED is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+# CONFIG_INLINE_SPIN_TRYLOCK is not set
+# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK is not set
+# CONFIG_INLINE_SPIN_LOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_SPIN_UNLOCK is not set
+# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_READ_TRYLOCK is not set
+# CONFIG_INLINE_READ_LOCK is not set
+# CONFIG_INLINE_READ_LOCK_BH is not set
+# CONFIG_INLINE_READ_LOCK_IRQ is not set
+# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_READ_UNLOCK is not set
+# CONFIG_INLINE_READ_UNLOCK_BH is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQ is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_WRITE_TRYLOCK is not set
+# CONFIG_INLINE_WRITE_LOCK is not set
+# CONFIG_INLINE_WRITE_LOCK_BH is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_WRITE_UNLOCK is not set
+# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
+# CONFIG_MUTEX_SPIN_ON_OWNER is not set
+CONFIG_FREEZER=y
+
+#
+# System type
+#
+CONFIG_CPU_SH4=y
+CONFIG_CPU_SH4A=y
+CONFIG_CPU_SHX3=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 is not set
+# CONFIG_CPU_SUBTYPE_SH7757 is not set
+# 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=y
+# 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=0x60000000
+CONFIG_MEMORY_SIZE=0x20000000
+# CONFIG_29BIT is not set
+CONFIG_32BIT=y
+CONFIG_PMB=y
+# CONFIG_PMB_LEGACY is not set
+CONFIG_X2TLB=y
+CONFIG_VSYSCALL=y
+# CONFIG_NUMA is not set
+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_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+CONFIG_ARCH_MEMORY_PROBE=y
+CONFIG_IOREMAP_FIXED=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_HUGETLB_PAGE_SIZE_64K is not set
+# CONFIG_HUGETLB_PAGE_SIZE_256K is not set
+CONFIG_HUGETLB_PAGE_SIZE_1MB=y
+# CONFIG_HUGETLB_PAGE_SIZE_4MB is not set
+# CONFIG_HUGETLB_PAGE_SIZE_64MB is not set
+# CONFIG_HUGETLB_PAGE_SIZE_512MB is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+CONFIG_SPARSEMEM_STATIC=y
+CONFIG_MEMORY_HOTPLUG=y
+CONFIG_MEMORY_HOTPLUG_SPARSE=y
+CONFIG_MEMORY_HOTREMOVE=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=1
+CONFIG_KSM=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=y
+CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_SR_RB=y
+CONFIG_CPU_HAS_PTEAEX=y
+CONFIG_CPU_HAS_FPU=y
+
+#
+# Board support
+#
+CONFIG_SH_SDK7786=y
+# CONFIG_SH_URQUELL is not set
+
+#
+# Timer and clock configuration
+#
+CONFIG_SH_TIMER_TMU=y
+CONFIG_SH_CLK_CPG=y
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+# CONFIG_CPU_FREQ_DEBUG is not set
+CONFIG_CPU_FREQ_STAT=y
+# CONFIG_CPU_FREQ_STAT_DETAILS is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=m
+CONFIG_CPU_FREQ_GOV_USERSPACE=m
+CONFIG_CPU_FREQ_GOV_ONDEMAND=m
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
+CONFIG_SH_CPU_FREQ=y
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+
+#
+# Additional SuperH Device Drivers
+#
+CONFIG_HEARTBEAT=y
+# CONFIG_PUSH_SWITCH is not set
+
+#
+# Kernel features
+#
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_SCHED_HRTICK=y
+CONFIG_KEXEC=y
+# CONFIG_CRASH_DUMP is not set
+CONFIG_SECCOMP=y
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_GUSA=y
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_ENTRY_OFFSET=0x00001000
+CONFIG_CMDLINE_OVERWRITE=y
+# CONFIG_CMDLINE_EXTEND is not set
+CONFIG_CMDLINE="console=ttySC1,115200 earlyprintk=sh-sci.1,115200 root=/dev/sda1 nmi_debug=state,debounce rootdelay=10"
+
+#
+# Bus options
+#
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCIEPORTBUS=y
+CONFIG_PCIEAER=y
+# CONFIG_PCIE_ECRC is not set
+CONFIG_PCIEAER_INJECT=y
+CONFIG_PCIEASPM=y
+CONFIG_PCIEASPM_DEBUG=y
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCI_LEGACY is not set
+CONFIG_PCI_DEBUG=y
+# CONFIG_PCI_STUB is not set
+# CONFIG_PCI_IOV is not set
+# CONFIG_PCCARD is not set
+# CONFIG_HOTPLUG_PCI 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=y
+
+#
+# Power management options (EXPERIMENTAL)
+#
+CONFIG_PM=y
+CONFIG_PM_DEBUG=y
+CONFIG_PM_VERBOSE=y
+# CONFIG_HIBERNATION is not set
+CONFIG_PM_RUNTIME=y
+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_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE 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=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP 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=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# 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_RDS 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_NET_DROP_MONITOR 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=y
+# CONFIG_CFG80211 is not set
+# CONFIG_LIB80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+# 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_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+# CONFIG_MTD is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+
+#
+# DRBD disabled because PROC_FS, INET or CONNECTOR not selected
+#
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_XIP 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=y
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_PHANTOM is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_HP_ILO is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_TI_DAC7512 is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
+# CONFIG_BE2ISCSI is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_HPSA is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_3W_SAS is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_MPT2SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
+# CONFIG_FCOE is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_PMCRAID is not set
+# CONFIG_SCSI_PM8001 is not set
+# CONFIG_SCSI_SRP is not set
+# CONFIG_SCSI_BFA_FC is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
+CONFIG_ATA_VERBOSE_ERROR=y
+CONFIG_SATA_PMP=y
+# CONFIG_SATA_AHCI is not set
+CONFIG_SATA_SIL24=y
+CONFIG_ATA_SFF=y
+# CONFIG_SATA_SVW is not set
+# CONFIG_ATA_PIIX is not set
+# CONFIG_SATA_MV is not set
+# CONFIG_SATA_NV is not set
+# CONFIG_PDC_ADMA is not set
+# CONFIG_SATA_QSTOR is not set
+# CONFIG_SATA_PROMISE is not set
+# CONFIG_SATA_SX4 is not set
+# CONFIG_SATA_SIL is not set
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_ULI is not set
+# CONFIG_SATA_VIA is not set
+# CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
+# CONFIG_PATA_ALI is not set
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATP867X is not set
+# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD640_PCI is not set
+# CONFIG_PATA_CMD64X is not set
+# CONFIG_PATA_CS5520 is not set
+# CONFIG_PATA_CS5530 is not set
+# CONFIG_PATA_CYPRESS is not set
+# CONFIG_PATA_EFAR is not set
+# CONFIG_ATA_GENERIC is not set
+# CONFIG_PATA_HPT366 is not set
+# CONFIG_PATA_HPT37X is not set
+# CONFIG_PATA_HPT3X2N is not set
+# CONFIG_PATA_HPT3X3 is not set
+# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_IT8213 is not set
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_OLDPIIX is not set
+# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NINJA32 is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_NS87415 is not set
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RDC is not set
+# CONFIG_PATA_RZ1000 is not set
+# CONFIG_PATA_SC1200 is not set
+# CONFIG_PATA_SERVERWORKS is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_SIS is not set
+# CONFIG_PATA_TOSHIBA is not set
+# CONFIG_PATA_VIA is not set
+# CONFIG_PATA_WINBOND is not set
+CONFIG_PATA_PLATFORM=y
+# CONFIG_PATA_SCH is not set
+# CONFIG_MD is not set
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# The newer stack is recommended.
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+# CONFIG_I2O is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_ARCNET is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_FIXED_PHY is not set
+CONFIG_MDIO_BITBANG=y
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_STNIC is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+CONFIG_SMC91X=y
+# CONFIG_ENC28J60 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_SMC911X is not set
+CONFIG_SMSC911X=y
+# CONFIG_DNET is not set
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851 is not set
+# CONFIG_KS8851_MLL is not set
+# CONFIG_ATL2 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_TR is not set
+CONFIG_WLAN=y
+# CONFIG_ATMEL is not set
+# CONFIG_PRISM54 is not set
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_HOSTAP is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_VMXNET3 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
+# CONFIG_INPUT_SPARSEKMAP is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ADP5588 is not set
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_QT2160 is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_MAX7359 is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_SH_KEYSC is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_SENTELIC is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_SYNAPTICS_I2C 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=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_ALTERA_PS2 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 is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_MAX3100 is not set
+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_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# PC SMBus host controller drivers
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_ISCH is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_DESIGNWARE is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SH_MOBILE is not set
+# 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
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# 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=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_SH_MSIOF is not set
+# CONFIG_SPI_SH_SCI is not set
+# CONFIG_SPI_XILINX is not set
+# CONFIG_SPI_DESIGNWARE is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_ALIM7101_WDT is not set
+# CONFIG_SH_WDT is not set
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG 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_MFD_SH_MOBILE_SDHI is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_MC13783 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_EZX_PCAP is not set
+# CONFIG_MFD_88PM8607 is not set
+# CONFIG_AB4500_CORE is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+CONFIG_VGA_ARB=y
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+# 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=y
+CONFIG_HID=y
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_HID_DRAGONRISE is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_TWINHAN is not set
+# CONFIG_HID_KENSINGTON is not set
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MICROSOFT is not set
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_NTRIG is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SONY is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_WHCI_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+# CONFIG_USB_GADGET_MUSB_HDRC is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+# CONFIG_USB_GADGET_DEBUG_FS is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_R8A66597 is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C_HSOTG is not set
+# CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+CONFIG_USB_GADGET_M66592=y
+CONFIG_USB_M66592=y
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LANGWELL is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+# CONFIG_USB_ZERO is not set
+# CONFIG_USB_AUDIO is not set
+# CONFIG_USB_ETH is not set
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_MASS_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+# CONFIG_USB_CDC_COMPOSITE is not set
+# CONFIG_USB_G_MULTI is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_UWB 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_INFINIBAND is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+CONFIG_RTC_DRV_MAX6900=y
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_BQ32K is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+# CONFIG_RTC_DRV_PCF2123 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_SH=y
+# CONFIG_RTC_DRV_GENERIC is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+CONFIG_UIO=m
+# CONFIG_UIO_CIF is not set
+# CONFIG_UIO_PDRV is not set
+# CONFIG_UIO_PDRV_GENIRQ is not set
+# CONFIG_UIO_SMX is not set
+# CONFIG_UIO_AEC is not set
+# CONFIG_UIO_SERCOS3 is not set
+# CONFIG_UIO_PCI_GENERIC is not set
+
+#
+# TI VLYNQ
+#
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# 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_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# 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=y
+CONFIG_HUGETLB_PAGE=y
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_PRINTK_TIME=y
+CONFIG_ENABLE_WARN_DEPRECATED=y
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_SHIRQ=y
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_PREEMPT=y
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+CONFIG_DEBUG_VM=y
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+# CONFIG_PAGE_POISONING is not set
+CONFIG_NOP_TRACER=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_SYSCALL_TRACEPOINTS=y
+CONFIG_RING_BUFFER=y
+CONFIG_EVENT_TRACING=y
+CONFIG_CONTEXT_SWITCH_TRACER=y
+CONFIG_TRACING=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+# CONFIG_FTRACE_SYSCALLS is not set
+# CONFIG_BOOT_TRACER is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+CONFIG_KSYM_TRACER=y
+# CONFIG_PROFILE_KSYM_TRACER is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_RING_BUFFER_BENCHMARK 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_KGDB is not set
+# CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_STACK_DEBUG is not set
+CONFIG_DEBUG_STACK_USAGE=y
+# CONFIG_4KSTACKS is not set
+CONFIG_DUMP_CODE=y
+CONFIG_DWARF_UNWINDER=y
+# CONFIG_SH_NO_BSS_INIT is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_DEFAULT_SECURITY_SELINUX is not set
+# CONFIG_DEFAULT_SECURITY_SMACK is not set
+# CONFIG_DEFAULT_SECURITY_TOMOYO is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_GHASH is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+CONFIG_BINARY_PRINTF=y
+
+#
+# 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 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+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/drivers/dma/dma-pvr2.c b/arch/sh/drivers/dma/dma-pvr2.c
index 391cbe1..3cee58e 100644
--- a/arch/sh/drivers/dma/dma-pvr2.c
+++ b/arch/sh/drivers/dma/dma-pvr2.c
@@ -40,10 +40,10 @@
 
 static int pvr2_request_dma(struct dma_channel *chan)
 {
-	if (ctrl_inl(PVR2_DMA_MODE) != 0)
+	if (__raw_readl(PVR2_DMA_MODE) != 0)
 		return -EBUSY;
 
-	ctrl_outl(0, PVR2_DMA_LMMODE0);
+	__raw_writel(0, PVR2_DMA_LMMODE0);
 
 	return 0;
 }
@@ -60,9 +60,9 @@
 
 	xfer_complete = 0;
 
-	ctrl_outl(chan->dar, PVR2_DMA_ADDR);
-	ctrl_outl(chan->count, PVR2_DMA_COUNT);
-	ctrl_outl(chan->mode & DMA_MODE_MASK, PVR2_DMA_MODE);
+	__raw_writel(chan->dar, PVR2_DMA_ADDR);
+	__raw_writel(chan->count, PVR2_DMA_COUNT);
+	__raw_writel(chan->mode & DMA_MODE_MASK, PVR2_DMA_MODE);
 
 	return 0;
 }
diff --git a/arch/sh/drivers/dma/dma-sh.c b/arch/sh/drivers/dma/dma-sh.c
index 37fb5b8..8272087 100644
--- a/arch/sh/drivers/dma/dma-sh.c
+++ b/arch/sh/drivers/dma/dma-sh.c
@@ -52,11 +52,14 @@
  *
  * iterations to complete the transfer.
  */
+static unsigned int ts_shift[] = TS_SHIFT;
 static inline unsigned int calc_xmit_shift(struct dma_channel *chan)
 {
-	u32 chcr = ctrl_inl(dma_base_addr[chan->chan] + CHCR);
+	u32 chcr = __raw_readl(dma_base_addr[chan->chan] + CHCR);
+	int cnt = ((chcr & CHCR_TS_LOW_MASK) >> CHCR_TS_LOW_SHIFT) |
+		((chcr & CHCR_TS_HIGH_MASK) >> CHCR_TS_HIGH_SHIFT);
 
-	return ts_shift[(chcr & CHCR_TS_MASK)>>CHCR_TS_SHIFT];
+	return ts_shift[cnt];
 }
 
 /*
@@ -70,13 +73,13 @@
 	struct dma_channel *chan = dev_id;
 	u32 chcr;
 
-	chcr = ctrl_inl(dma_base_addr[chan->chan] + CHCR);
+	chcr = __raw_readl(dma_base_addr[chan->chan] + CHCR);
 
 	if (!(chcr & CHCR_TE))
 		return IRQ_NONE;
 
 	chcr &= ~(CHCR_IE | CHCR_DE);
-	ctrl_outl(chcr, (dma_base_addr[chan->chan] + CHCR));
+	__raw_writel(chcr, (dma_base_addr[chan->chan] + CHCR));
 
 	wake_up(&chan->wait_queue);
 
@@ -115,7 +118,7 @@
 		chan->flags &= ~DMA_TEI_CAPABLE;
 	}
 
-	ctrl_outl(chcr, (dma_base_addr[chan->chan] + CHCR));
+	__raw_writel(chcr, (dma_base_addr[chan->chan] + CHCR));
 
 	chan->flags |= DMA_CONFIGURED;
 	return 0;
@@ -126,13 +129,13 @@
 	int irq;
 	u32 chcr;
 
-	chcr = ctrl_inl(dma_base_addr[chan->chan] + CHCR);
+	chcr = __raw_readl(dma_base_addr[chan->chan] + CHCR);
 	chcr |= CHCR_DE;
 
 	if (chan->flags & DMA_TEI_CAPABLE)
 		chcr |= CHCR_IE;
 
-	ctrl_outl(chcr, (dma_base_addr[chan->chan] + CHCR));
+	__raw_writel(chcr, (dma_base_addr[chan->chan] + CHCR));
 
 	if (chan->flags & DMA_TEI_CAPABLE) {
 		irq = get_dmte_irq(chan->chan);
@@ -150,9 +153,9 @@
 		disable_irq(irq);
 	}
 
-	chcr = ctrl_inl(dma_base_addr[chan->chan] + CHCR);
+	chcr = __raw_readl(dma_base_addr[chan->chan] + CHCR);
 	chcr &= ~(CHCR_DE | CHCR_TE | CHCR_IE);
-	ctrl_outl(chcr, (dma_base_addr[chan->chan] + CHCR));
+	__raw_writel(chcr, (dma_base_addr[chan->chan] + CHCR));
 }
 
 static int sh_dmac_xfer_dma(struct dma_channel *chan)
@@ -183,12 +186,12 @@
 	 */
 	if (chan->sar || (mach_is_dreamcast() &&
 			  chan->chan == PVR2_CASCADE_CHAN))
-		ctrl_outl(chan->sar, (dma_base_addr[chan->chan]+SAR));
+		__raw_writel(chan->sar, (dma_base_addr[chan->chan]+SAR));
 	if (chan->dar || (mach_is_dreamcast() &&
 			  chan->chan == PVR2_CASCADE_CHAN))
-		ctrl_outl(chan->dar, (dma_base_addr[chan->chan] + DAR));
+		__raw_writel(chan->dar, (dma_base_addr[chan->chan] + DAR));
 
-	ctrl_outl(chan->count >> calc_xmit_shift(chan),
+	__raw_writel(chan->count >> calc_xmit_shift(chan),
 		(dma_base_addr[chan->chan] + TCR));
 
 	sh_dmac_enable_dma(chan);
@@ -198,10 +201,10 @@
 
 static int sh_dmac_get_dma_residue(struct dma_channel *chan)
 {
-	if (!(ctrl_inl(dma_base_addr[chan->chan] + CHCR) & CHCR_DE))
+	if (!(__raw_readl(dma_base_addr[chan->chan] + CHCR) & CHCR_DE))
 		return 0;
 
-	return ctrl_inl(dma_base_addr[chan->chan] + TCR)
+	return __raw_readl(dma_base_addr[chan->chan] + TCR)
 		 << calc_xmit_shift(chan);
 }
 
diff --git a/arch/sh/drivers/dma/dmabrg.c b/arch/sh/drivers/dma/dmabrg.c
index 5e22689..72622e3 100644
--- a/arch/sh/drivers/dma/dmabrg.c
+++ b/arch/sh/drivers/dma/dmabrg.c
@@ -86,8 +86,8 @@
 	unsigned long dcr;
 	unsigned int i;
 
-	dcr = ctrl_inl(DMABRGCR);
-	ctrl_outl(dcr & ~0x00ff0003, DMABRGCR);	/* ack all */
+	dcr = __raw_readl(DMABRGCR);
+	__raw_writel(dcr & ~0x00ff0003, DMABRGCR);	/* ack all */
 	dcr &= dcr >> 8;	/* ignore masked */
 
 	/* USB stuff, get it out of the way first */
@@ -109,17 +109,17 @@
 static void dmabrg_disable_irq(unsigned int dmairq)
 {
 	unsigned long dcr;
-	dcr = ctrl_inl(DMABRGCR);
+	dcr = __raw_readl(DMABRGCR);
 	dcr &= ~(1 << ((dmairq > 1) ? dmairq + 22 : dmairq + 8));
-	ctrl_outl(dcr, DMABRGCR);
+	__raw_writel(dcr, DMABRGCR);
 }
 
 static void dmabrg_enable_irq(unsigned int dmairq)
 {
 	unsigned long dcr;
-	dcr = ctrl_inl(DMABRGCR);
+	dcr = __raw_readl(DMABRGCR);
 	dcr |= (1 << ((dmairq > 1) ? dmairq + 22 : dmairq + 8));
-	ctrl_outl(dcr, DMABRGCR);
+	__raw_writel(dcr, DMABRGCR);
 }
 
 int dmabrg_request_irq(unsigned int dmairq, void(*handler)(void*),
@@ -165,13 +165,13 @@
 		printk(KERN_INFO "DMABRG: DMAC ch0 not reserved!\n");
 #endif
 
-	ctrl_outl(0, DMABRGCR);
-	ctrl_outl(0, DMACHCR0);
-	ctrl_outl(0x94000000, DMARSRA);	/* enable DMABRG in DMAC 0 */
+	__raw_writel(0, DMABRGCR);
+	__raw_writel(0, DMACHCR0);
+	__raw_writel(0x94000000, DMARSRA);	/* enable DMABRG in DMAC 0 */
 
 	/* enable DMABRG mode, enable the DMAC */
-	or = ctrl_inl(DMAOR);
-	ctrl_outl(or | DMAOR_BRG | DMAOR_DMEN, DMAOR);
+	or = __raw_readl(DMAOR);
+	__raw_writel(or | DMAOR_BRG | DMAOR_DMEN, DMAOR);
 
 	ret = request_irq(DMABRGI0, dmabrg_irq, IRQF_DISABLED,
 			"DMABRG USB address error", NULL);
diff --git a/arch/sh/drivers/heartbeat.c b/arch/sh/drivers/heartbeat.c
index a9339a6..2acbc79 100644
--- a/arch/sh/drivers/heartbeat.c
+++ b/arch/sh/drivers/heartbeat.c
@@ -1,7 +1,7 @@
 /*
  * Generic heartbeat driver for regular LED banks
  *
- * Copyright (C) 2007  Paul Mundt
+ * Copyright (C) 2007 - 2010  Paul Mundt
  *
  * Most SH reference boards include a number of individual LEDs that can
  * be independently controlled (either via a pre-defined hardware
@@ -27,7 +27,7 @@
 #include <asm/heartbeat.h>
 
 #define DRV_NAME "heartbeat"
-#define DRV_VERSION "0.1.1"
+#define DRV_VERSION "0.1.2"
 
 static unsigned char default_bit_pos[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
 
@@ -98,7 +98,7 @@
 			return -ENOMEM;
 	}
 
-	hd->base = ioremap_nocache(res->start, res->end - res->start + 1);
+	hd->base = ioremap_nocache(res->start, resource_size(res));
 	if (unlikely(!hd->base)) {
 		dev_err(&pdev->dev, "ioremap failed\n");
 
@@ -117,8 +117,20 @@
 	for (i = 0; i < hd->nr_bits; i++)
 		hd->mask |= (1 << hd->bit_pos[i]);
 
-	if (!hd->regsize)
-		hd->regsize = 8;	/* default access size */
+	if (!hd->regsize) {
+		switch (res->flags & IORESOURCE_MEM_TYPE_MASK) {
+		case IORESOURCE_MEM_32BIT:
+			hd->regsize = 32;
+			break;
+		case IORESOURCE_MEM_16BIT:
+			hd->regsize = 16;
+			break;
+		case IORESOURCE_MEM_8BIT:
+		default:
+			hd->regsize = 8;
+			break;
+		}
+	}
 
 	setup_timer(&hd->timer, heartbeat_timer, (unsigned long)hd);
 	platform_set_drvdata(pdev, hd);
diff --git a/arch/sh/drivers/pci/Makefile b/arch/sh/drivers/pci/Makefile
index 08af1f4..4a59e68 100644
--- a/arch/sh/drivers/pci/Makefile
+++ b/arch/sh/drivers/pci/Makefile
@@ -1,14 +1,14 @@
 #
 # Makefile for the PCI specific kernel interface routines under Linux.
 #
-obj-y					+= pci.o
+obj-y					+= common.o pci.o
 
 obj-$(CONFIG_CPU_SUBTYPE_SH7751)	+= pci-sh7751.o ops-sh4.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7751R)	+= pci-sh7751.o ops-sh4.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7763)	+= pci-sh7780.o ops-sh4.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7780)	+= pci-sh7780.o ops-sh4.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7785)	+= pci-sh7780.o ops-sh4.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7786)	+= ops-sh7786.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7786)	+= pcie-sh7786.o ops-sh7786.o
 obj-$(CONFIG_CPU_SH5)			+= pci-sh5.o ops-sh5.o
 
 obj-$(CONFIG_SH_DREAMCAST)		+= ops-dreamcast.o fixups-dreamcast.o \
@@ -25,4 +25,3 @@
 obj-$(CONFIG_SH_LANDISK)		+= fixups-landisk.o
 obj-$(CONFIG_SH_LBOX_RE2)		+= fixups-rts7751r2d.o
 obj-$(CONFIG_SH_CAYMAN)			+= fixups-cayman.o
-obj-$(CONFIG_SH_URQUELL)		+= pcie-sh7786.o
diff --git a/arch/sh/drivers/pci/common.c b/arch/sh/drivers/pci/common.c
new file mode 100644
index 0000000..dbf1381
--- /dev/null
+++ b/arch/sh/drivers/pci/common.c
@@ -0,0 +1,162 @@
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+#include <linux/kernel.h>
+
+/*
+ * These functions are used early on before PCI scanning is done
+ * and all of the pci_dev and pci_bus structures have been created.
+ */
+static struct pci_dev *fake_pci_dev(struct pci_channel *hose,
+	int top_bus, int busnr, int devfn)
+{
+	static struct pci_dev dev;
+	static struct pci_bus bus;
+
+	dev.bus = &bus;
+	dev.sysdata = hose;
+	dev.devfn = devfn;
+	bus.number = busnr;
+	bus.sysdata = hose;
+	bus.ops = hose->pci_ops;
+
+	if(busnr != top_bus)
+		/* Fake a parent bus structure. */
+		bus.parent = &bus;
+	else
+		bus.parent = NULL;
+
+	return &dev;
+}
+
+#define EARLY_PCI_OP(rw, size, type)					\
+int __init early_##rw##_config_##size(struct pci_channel *hose,		\
+	int top_bus, int bus, int devfn, int offset, type value)	\
+{									\
+	return pci_##rw##_config_##size(				\
+		fake_pci_dev(hose, top_bus, bus, devfn),		\
+		offset, value);						\
+}
+
+EARLY_PCI_OP(read, byte, u8 *)
+EARLY_PCI_OP(read, word, u16 *)
+EARLY_PCI_OP(read, dword, u32 *)
+EARLY_PCI_OP(write, byte, u8)
+EARLY_PCI_OP(write, word, u16)
+EARLY_PCI_OP(write, dword, u32)
+
+int __init pci_is_66mhz_capable(struct pci_channel *hose,
+				int top_bus, int current_bus)
+{
+	u32 pci_devfn;
+	unsigned short vid;
+	int cap66 = -1;
+	u16 stat;
+
+	printk(KERN_INFO "PCI: Checking 66MHz capabilities...\n");
+
+	for (pci_devfn = 0; pci_devfn < 0xff; pci_devfn++) {
+		if (PCI_FUNC(pci_devfn))
+			continue;
+		if (early_read_config_word(hose, top_bus, current_bus,
+					   pci_devfn, PCI_VENDOR_ID, &vid) !=
+		    PCIBIOS_SUCCESSFUL)
+			continue;
+		if (vid == 0xffff)
+			continue;
+
+		/* check 66MHz capability */
+		if (cap66 < 0)
+			cap66 = 1;
+		if (cap66) {
+			early_read_config_word(hose, top_bus, current_bus,
+					       pci_devfn, PCI_STATUS, &stat);
+			if (!(stat & PCI_STATUS_66MHZ)) {
+				printk(KERN_DEBUG
+				       "PCI: %02x:%02x not 66MHz capable.\n",
+				       current_bus, pci_devfn);
+				cap66 = 0;
+				break;
+			}
+		}
+	}
+
+	return cap66 > 0;
+}
+
+static void pcibios_enable_err(unsigned long __data)
+{
+	struct pci_channel *hose = (struct pci_channel *)__data;
+
+	del_timer(&hose->err_timer);
+	printk(KERN_DEBUG "PCI: re-enabling error IRQ.\n");
+	enable_irq(hose->err_irq);
+}
+
+static void pcibios_enable_serr(unsigned long __data)
+{
+	struct pci_channel *hose = (struct pci_channel *)__data;
+
+	del_timer(&hose->serr_timer);
+	printk(KERN_DEBUG "PCI: re-enabling system error IRQ.\n");
+	enable_irq(hose->serr_irq);
+}
+
+void pcibios_enable_timers(struct pci_channel *hose)
+{
+	if (hose->err_irq) {
+		init_timer(&hose->err_timer);
+		hose->err_timer.data = (unsigned long)hose;
+		hose->err_timer.function = pcibios_enable_err;
+	}
+
+	if (hose->serr_irq) {
+		init_timer(&hose->serr_timer);
+		hose->serr_timer.data = (unsigned long)hose;
+		hose->serr_timer.function = pcibios_enable_serr;
+	}
+}
+
+/*
+ * A simple handler for the regular PCI status errors, called from IRQ
+ * context.
+ */
+unsigned int pcibios_handle_status_errors(unsigned long addr,
+					  unsigned int status,
+					  struct pci_channel *hose)
+{
+	unsigned int cmd = 0;
+
+	if (status & PCI_STATUS_REC_MASTER_ABORT) {
+		printk(KERN_DEBUG "PCI: master abort, pc=0x%08lx\n", addr);
+		cmd |= PCI_STATUS_REC_MASTER_ABORT;
+	}
+
+	if (status & PCI_STATUS_REC_TARGET_ABORT) {
+		printk(KERN_DEBUG "PCI: target abort: ");
+		pcibios_report_status(PCI_STATUS_REC_TARGET_ABORT |
+				      PCI_STATUS_SIG_TARGET_ABORT |
+				      PCI_STATUS_REC_MASTER_ABORT, 1);
+		printk("\n");
+
+		cmd |= PCI_STATUS_REC_TARGET_ABORT;
+	}
+
+	if (status & (PCI_STATUS_PARITY | PCI_STATUS_DETECTED_PARITY)) {
+		printk(KERN_DEBUG "PCI: parity error detected: ");
+		pcibios_report_status(PCI_STATUS_PARITY |
+				      PCI_STATUS_DETECTED_PARITY, 1);
+		printk("\n");
+
+		cmd |= PCI_STATUS_PARITY | PCI_STATUS_DETECTED_PARITY;
+
+		/* Now back off of the IRQ for awhile */
+		if (hose->err_irq) {
+			disable_irq_nosync(hose->err_irq);
+			hose->err_timer.expires = jiffies + HZ;
+			add_timer(&hose->err_timer);
+		}
+	}
+
+	return cmd;
+}
diff --git a/arch/sh/drivers/pci/fixups-dreamcast.c b/arch/sh/drivers/pci/fixups-dreamcast.c
index ed7f489..942ef4f 100644
--- a/arch/sh/drivers/pci/fixups-dreamcast.c
+++ b/arch/sh/drivers/pci/fixups-dreamcast.c
@@ -39,7 +39,7 @@
 		/*
 		 * We also assume that dev->devfn == 0
 		 */
-		dev->resource[1].start	= p->io_resource->start  + 0x100;
+		dev->resource[1].start	= p->resources[0].start  + 0x100;
 		dev->resource[1].end	= dev->resource[1].start + 0x200 - 1;
 
 		/*
diff --git a/arch/sh/drivers/pci/fixups-r7780rp.c b/arch/sh/drivers/pci/fixups-r7780rp.c
index 15ca65c..08b2d86 100644
--- a/arch/sh/drivers/pci/fixups-r7780rp.c
+++ b/arch/sh/drivers/pci/fixups-r7780rp.c
@@ -22,15 +22,3 @@
 {
 	return irq_tab[slot];
 }
-
-int pci_fixup_pcic(struct pci_channel *chan)
-{
-	pci_write_reg(chan, 0x000043ff, SH4_PCIINTM);
-	pci_write_reg(chan, 0x00000000, SH7780_PCIIBAR);
-	pci_write_reg(chan, 0x08000000, SH7780_PCICSCR0);
-	pci_write_reg(chan, 0x0000001b, SH7780_PCICSAR0);
-	pci_write_reg(chan, 0xfd000000, SH7780_PCICSCR1);
-	pci_write_reg(chan, 0x0000000f, SH7780_PCICSAR1);
-
-	return 0;
-}
diff --git a/arch/sh/drivers/pci/fixups-rts7751r2d.c b/arch/sh/drivers/pci/fixups-rts7751r2d.c
index 7898f14..e248516 100644
--- a/arch/sh/drivers/pci/fixups-rts7751r2d.c
+++ b/arch/sh/drivers/pci/fixups-rts7751r2d.c
@@ -43,7 +43,7 @@
 {
 	unsigned long bcr1, mcr;
 
-	bcr1 = ctrl_inl(SH7751_BCR1);
+	bcr1 = __raw_readl(SH7751_BCR1);
 	bcr1 |= 0x40080000;	/* Enable Bit 19 BREQEN, set PCIC to slave */
 	pci_write_reg(chan, bcr1, SH4_PCIBCR1);
 
@@ -54,7 +54,7 @@
 	pci_write_reg(chan, 0xfb900047, SH7751_PCICONF1);
 	pci_write_reg(chan, 0xab000001, SH7751_PCICONF4);
 
-	mcr = ctrl_inl(SH7751_MCR);
+	mcr = __raw_readl(SH7751_MCR);
 	mcr = (mcr & PCIMCR_MRSET_OFF) & PCIMCR_RFSH_OFF;
 	pci_write_reg(chan, mcr, SH4_PCIMCR);
 
diff --git a/arch/sh/drivers/pci/fixups-sdk7780.c b/arch/sh/drivers/pci/fixups-sdk7780.c
index 250b0ed..0930f98 100644
--- a/arch/sh/drivers/pci/fixups-sdk7780.c
+++ b/arch/sh/drivers/pci/fixups-sdk7780.c
@@ -31,22 +31,3 @@
 {
        return sdk7780_irq_tab[pin-1][slot];
 }
-int pci_fixup_pcic(struct pci_channel *chan)
-{
-	/* Enable all interrupts, so we know what to fix */
-	pci_write_reg(chan, 0x0000C3FF, SH7780_PCIIMR);
-
-	/* Set up standard PCI config registers */
-	pci_write_reg(chan, 0x08000000, SH7780_PCIMBAR0);	/* PCI */
-	pci_write_reg(chan, 0x08000000, SH4_PCILAR0);	/* SHwy */
-	pci_write_reg(chan, 0x07F00001, SH4_PCILSR0);	/* size 128M w/ MBAR */
-
-	pci_write_reg(chan, 0x00000000, SH7780_PCIMBAR1);
-	pci_write_reg(chan, 0x00000000, SH4_PCILAR1);
-	pci_write_reg(chan, 0x00000000, SH4_PCILSR1);
-
-	pci_write_reg(chan, 0xAB000801, SH7780_PCIIBAR);
-	pci_write_reg(chan, 0xA5000C01, SH4_PCICR);
-
-	return 0;
-}
diff --git a/arch/sh/drivers/pci/fixups-se7751.c b/arch/sh/drivers/pci/fixups-se7751.c
index 475fa9f..a4c7d3a 100644
--- a/arch/sh/drivers/pci/fixups-se7751.c
+++ b/arch/sh/drivers/pci/fixups-se7751.c
@@ -97,12 +97,12 @@
 	* meaning all calls go straight through... use BUG_ON to
 	* catch erroneous assumption.
 	*/
-	BUG_ON(chan->mem_resource->start != SH7751_PCI_MEMORY_BASE);
+	BUG_ON(chan->resources[1].start != SH7751_PCI_MEMORY_BASE);
 
-	PCIC_WRITE(SH7751_PCIMBR, chan->mem_resource->start);
+	PCIC_WRITE(SH7751_PCIMBR, chan->resources[1].start);
 
 	/* Set IOBR for window containing area specified in pci.h */
-	PCIC_WRITE(SH7751_PCIIOBR, (chan->io_resource->start & SH7751_PCIIOBR_MASK));
+	PCIC_WRITE(SH7751_PCIIOBR, (chan->resources[0].start & SH7751_PCIIOBR_MASK));
 
 	/* All done, may as well say so... */
 	printk("SH7751 PCI: Finished initialization of the PCI controller\n");
diff --git a/arch/sh/drivers/pci/ops-sh4.c b/arch/sh/drivers/pci/ops-sh4.c
index 78bebeb..0b81999 100644
--- a/arch/sh/drivers/pci/ops-sh4.c
+++ b/arch/sh/drivers/pci/ops-sh4.c
@@ -16,7 +16,7 @@
  * Direct access to PCI hardware...
  */
 #define CONFIG_CMD(bus, devfn, where) \
-	(P1SEG | (bus->number << 16) | (devfn << 8) | (where & ~3))
+	(0x80000000 | (bus->number << 16) | (devfn << 8) | (where & ~3))
 
 static DEFINE_SPINLOCK(sh4_pci_lock);
 
@@ -102,34 +102,6 @@
 	.write		= sh4_pci_write,
 };
 
-/*
- * Not really related to pci_ops, but it's common and not worth shoving
- * somewhere else for now..
- */
-int __init sh4_pci_check_direct(struct pci_channel *chan)
-{
-	/*
-	 * Check if configuration works.
-	 */
-	unsigned int tmp = pci_read_reg(chan, SH4_PCIPAR);
-
-	pci_write_reg(chan, P1SEG, SH4_PCIPAR);
-
-	if (pci_read_reg(chan, SH4_PCIPAR) == P1SEG) {
-		pci_write_reg(chan, tmp, SH4_PCIPAR);
-		printk(KERN_INFO "PCI: Using configuration type 1\n");
-		request_region(chan->reg_base + SH4_PCIPAR, 8,
-			       "PCI conf1");
-		return 0;
-	}
-
-	pci_write_reg(chan, tmp, SH4_PCIPAR);
-
-	printk(KERN_ERR "PCI: %s failed\n", __func__);
-
-	return -EINVAL;
-}
-
 int __attribute__((weak)) pci_fixup_pcic(struct pci_channel *chan)
 {
 	/* Nothing to do. */
diff --git a/arch/sh/drivers/pci/pci-dreamcast.c b/arch/sh/drivers/pci/pci-dreamcast.c
index 210f9d4..6336941 100644
--- a/arch/sh/drivers/pci/pci-dreamcast.c
+++ b/arch/sh/drivers/pci/pci-dreamcast.c
@@ -25,25 +25,25 @@
 #include <asm/irq.h>
 #include <mach/pci.h>
 
-static struct resource gapspci_io_resource = {
-	.name	= "GAPSPCI IO",
-	.start	= GAPSPCI_BBA_CONFIG,
-	.end	= GAPSPCI_BBA_CONFIG + GAPSPCI_BBA_CONFIG_SIZE - 1,
-	.flags	= IORESOURCE_IO,
-};
-
-static struct resource gapspci_mem_resource = {
-	.name	= "GAPSPCI mem",
-	.start	= GAPSPCI_DMA_BASE,
-	.end	= GAPSPCI_DMA_BASE + GAPSPCI_DMA_SIZE - 1,
-	.flags	= IORESOURCE_MEM,
+static struct resource gapspci_resources[] = {
+	{
+		.name	= "GAPSPCI IO",
+		.start	= GAPSPCI_BBA_CONFIG,
+		.end	= GAPSPCI_BBA_CONFIG + GAPSPCI_BBA_CONFIG_SIZE - 1,
+		.flags	= IORESOURCE_IO,
+	},  {
+		.name	= "GAPSPCI mem",
+		.start	= GAPSPCI_DMA_BASE,
+		.end	= GAPSPCI_DMA_BASE + GAPSPCI_DMA_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
 };
 
 static struct pci_channel dreamcast_pci_controller = {
 	.pci_ops	= &gapspci_pci_ops,
-	.io_resource	= &gapspci_io_resource,
+	.resources	= gapspci_resources,
+	.nr_resources	= ARRAY_SIZE(gapspci_resources),
 	.io_offset	= 0x00000000,
-	.mem_resource	= &gapspci_mem_resource,
 	.mem_offset	= 0x00000000,
 };
 
@@ -95,8 +95,6 @@
 	outl(0x00002001, GAPSPCI_BBA_CONFIG+0x10);
 	outl(0x01000000, GAPSPCI_BBA_CONFIG+0x14);
 
-	register_pci_controller(&dreamcast_pci_controller);
-
-	return 0;
+	return register_pci_controller(&dreamcast_pci_controller);
 }
 arch_initcall(gapspci_init);
diff --git a/arch/sh/drivers/pci/pci-sh4.h b/arch/sh/drivers/pci/pci-sh4.h
index 3d5296c..cbf763b 100644
--- a/arch/sh/drivers/pci/pci-sh4.h
+++ b/arch/sh/drivers/pci/pci-sh4.h
@@ -49,6 +49,17 @@
   #define SH4_PCIINT_MWPD	  0x00000002	/* Master Write PERR Detect */
   #define SH4_PCIINT_MRPD	  0x00000001	/* Master Read PERR Detect */
 #define SH4_PCIINTM		0x118		/* PCI Interrupt Mask */
+  #define SH4_PCIINTM_TTADIM	  BIT(14)	/* Target-target abort interrupt */
+  #define SH4_PCIINTM_TMTOIM	  BIT(9)	/* Target retry timeout */
+  #define SH4_PCIINTM_MDEIM	  BIT(8)	/* Master function disable error */
+  #define SH4_PCIINTM_APEDIM	  BIT(7)	/* Address parity error detection */
+  #define SH4_PCIINTM_SDIM	  BIT(6)	/* SERR detection */
+  #define SH4_PCIINTM_DPEITWM	  BIT(5)	/* Data parity error for target write */
+  #define SH4_PCIINTM_PEDITRM	  BIT(4)	/* PERR detection for target read */
+  #define SH4_PCIINTM_TADIMM	  BIT(3)	/* Target abort for master */
+  #define SH4_PCIINTM_MADIMM	  BIT(2)	/* Master abort for master */
+  #define SH4_PCIINTM_MWPDIM	  BIT(1)	/* Master write data parity error */
+  #define SH4_PCIINTM_MRDPEIM	  BIT(0)	/* Master read data parity error */
 #define SH4_PCIALR		0x11C		/* Error Address Register */
 #define SH4_PCICLR		0x120		/* Error Command/Data */
   #define SH4_PCICLR_MPIO	  0x80000000
@@ -61,7 +72,7 @@
 #define SH4_PCIAINT		0x130		/* Arbiter Interrupt Register */
   #define SH4_PCIAINT_MBKN	  0x00002000	/* Master Broken Interrupt */
   #define SH4_PCIAINT_TBTO	  0x00001000	/* Target Bus Time Out */
-  #define SH4_PCIAINT_MBTO	  0x00001000	/* Master Bus Time Out */
+  #define SH4_PCIAINT_MBTO	  0x00000800	/* Master Bus Time Out */
   #define SH4_PCIAINT_TABT	  0x00000008	/* Target Abort */
   #define SH4_PCIAINT_MABT	  0x00000004	/* Master Abort */
   #define SH4_PCIAINT_RDPE	  0x00000002	/* Read Data Parity Error */
@@ -151,7 +162,6 @@
 
 /* arch/sh/kernel/drivers/pci/ops-sh4.c */
 extern struct pci_ops sh4_pci_ops;
-int sh4_pci_check_direct(struct pci_channel *chan);
 int pci_fixup_pcic(struct pci_channel *chan);
 
 struct sh4_pci_address_space {
@@ -167,13 +177,13 @@
 static inline void pci_write_reg(struct pci_channel *chan,
 				 unsigned long val, unsigned long reg)
 {
-	ctrl_outl(val, chan->reg_base + reg);
+	__raw_writel(val, chan->reg_base + reg);
 }
 
 static inline unsigned long pci_read_reg(struct pci_channel *chan,
 					 unsigned long reg)
 {
-	return ctrl_inl(chan->reg_base + reg);
+	return __raw_readl(chan->reg_base + reg);
 }
 
 #endif /* __PCI_SH4_H */
diff --git a/arch/sh/drivers/pci/pci-sh5.c b/arch/sh/drivers/pci/pci-sh5.c
index 873ed2b..0bf296c 100644
--- a/arch/sh/drivers/pci/pci-sh5.c
+++ b/arch/sh/drivers/pci/pci-sh5.c
@@ -89,14 +89,13 @@
 	return IRQ_NONE;
 }
 
-static struct resource sh5_io_resource = { /* place holder */ };
-static struct resource sh5_mem_resource = { /* place holder */ };
+static struct resource sh5_pci_resources[2];
 
 static struct pci_channel sh5pci_controller = {
 	.pci_ops		= &sh5_pci_ops,
-	.mem_resource		= &sh5_mem_resource,
+	.resources		= sh5_pci_resources,
+	.nr_resources		= ARRAY_SIZE(sh5_pci_resources),
 	.mem_offset		= 0x00000000,
-	.io_resource		= &sh5_io_resource,
 	.io_offset		= 0x00000000,
 };
 
@@ -210,14 +209,12 @@
         SH5PCI_WRITE(AINTM, ~0);
         SH5PCI_WRITE(PINTM, ~0);
 
-	sh5_io_resource.start = PCI_IO_AREA;
-	sh5_io_resource.end = PCI_IO_AREA + 0x10000;
+	sh5_pci_resources[0].start = PCI_IO_AREA;
+	sh5_pci_resources[0].end = PCI_IO_AREA + 0x10000;
 
-	sh5_mem_resource.start = memStart;
-	sh5_mem_resource.end = memStart + memSize;
+	sh5_pci_resources[1].start = memStart;
+	sh5_pci_resources[1].end = memStart + memSize;
 
-	register_pci_controller(&sh5pci_controller);
-
-	return 0;
+	return register_pci_controller(&sh5pci_controller);
 }
 arch_initcall(sh5pci_init);
diff --git a/arch/sh/drivers/pci/pci-sh5.h b/arch/sh/drivers/pci/pci-sh5.h
index f277628..3f01dec 100644
--- a/arch/sh/drivers/pci/pci-sh5.h
+++ b/arch/sh/drivers/pci/pci-sh5.h
@@ -86,14 +86,14 @@
 /* #define PCISH5_VCR_REG(x)                ( SH5PCI_VCR_BASE (PCISH5_VCR_##x)) */
 
 /* Write I/O functions */
-#define SH5PCI_WRITE(reg,val)        ctrl_outl((u32)(val),PCISH5_ICR_REG(reg))
-#define SH5PCI_WRITE_SHORT(reg,val)  ctrl_outw((u16)(val),PCISH5_ICR_REG(reg))
-#define SH5PCI_WRITE_BYTE(reg,val)   ctrl_outb((u8)(val),PCISH5_ICR_REG(reg))
+#define SH5PCI_WRITE(reg,val)        __raw_writel((u32)(val),PCISH5_ICR_REG(reg))
+#define SH5PCI_WRITE_SHORT(reg,val)  __raw_writew((u16)(val),PCISH5_ICR_REG(reg))
+#define SH5PCI_WRITE_BYTE(reg,val)   __raw_writeb((u8)(val),PCISH5_ICR_REG(reg))
 
 /* Read I/O functions */
-#define SH5PCI_READ(reg)             ctrl_inl(PCISH5_ICR_REG(reg))
-#define SH5PCI_READ_SHORT(reg)       ctrl_inw(PCISH5_ICR_REG(reg))
-#define SH5PCI_READ_BYTE(reg)        ctrl_inb(PCISH5_ICR_REG(reg))
+#define SH5PCI_READ(reg)             __raw_readl(PCISH5_ICR_REG(reg))
+#define SH5PCI_READ_SHORT(reg)       __raw_readw(PCISH5_ICR_REG(reg))
+#define SH5PCI_READ_BYTE(reg)        __raw_readb(PCISH5_ICR_REG(reg))
 
 /* Set PCI config bits */
 #define SET_CONFIG_BITS(bus,devfn,where)  ((((bus) << 16) | ((devfn) << 8) | ((where) & ~3)) | 0x80000000)
diff --git a/arch/sh/drivers/pci/pci-sh7751.c b/arch/sh/drivers/pci/pci-sh7751.c
index 70c1999..17811e5 100644
--- a/arch/sh/drivers/pci/pci-sh7751.c
+++ b/arch/sh/drivers/pci/pci-sh7751.c
@@ -44,25 +44,25 @@
 	return 1;
 }
 
-static struct resource sh7751_io_resource = {
-	.name	= "SH7751_IO",
-	.start	= SH7751_PCI_IO_BASE,
-	.end	= SH7751_PCI_IO_BASE + SH7751_PCI_IO_SIZE - 1,
-	.flags	= IORESOURCE_IO
-};
-
-static struct resource sh7751_mem_resource = {
-	.name	= "SH7751_mem",
-	.start	= SH7751_PCI_MEMORY_BASE,
-	.end	= SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1,
-	.flags	= IORESOURCE_MEM
+static struct resource sh7751_pci_resources[] = {
+	{
+		.name	= "SH7751_IO",
+		.start	= SH7751_PCI_IO_BASE,
+		.end	= SH7751_PCI_IO_BASE + SH7751_PCI_IO_SIZE - 1,
+		.flags	= IORESOURCE_IO
+	}, {
+		.name	= "SH7751_mem",
+		.start	= SH7751_PCI_MEMORY_BASE,
+		.end	= SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1,
+		.flags	= IORESOURCE_MEM
+	},
 };
 
 static struct pci_channel sh7751_pci_controller = {
 	.pci_ops	= &sh4_pci_ops,
-	.mem_resource	= &sh7751_mem_resource,
+	.resources	= sh7751_pci_resources,
+	.nr_resources	= ARRAY_SIZE(sh7751_pci_resources),
 	.mem_offset	= 0x00000000,
-	.io_resource	= &sh7751_io_resource,
 	.io_offset	= 0x00000000,
 	.io_map_base	= SH7751_PCI_IO_BASE,
 };
@@ -79,7 +79,6 @@
 	struct pci_channel *chan = &sh7751_pci_controller;
 	unsigned int id;
 	u32 word, reg;
-	int ret;
 
 	printk(KERN_NOTICE "PCI: Starting intialization.\n");
 
@@ -93,13 +92,10 @@
 		return -ENODEV;
 	}
 
-	if ((ret = sh4_pci_check_direct(chan)) != 0)
-		return ret;
-
 	/* Set the BCR's to enable PCI access */
-	reg = ctrl_inl(SH7751_BCR1);
+	reg = __raw_readl(SH7751_BCR1);
 	reg |= 0x80000;
-	ctrl_outl(reg, SH7751_BCR1);
+	__raw_writel(reg, SH7751_BCR1);
 
 	/* Turn the clocks back on (not done in reset)*/
 	pci_write_reg(chan, 0, SH4_PCICLKR);
@@ -132,13 +128,13 @@
 	/* Set the local 16MB PCI memory space window to
 	 * the lowest PCI mapped address
 	 */
-	word = chan->mem_resource->start & SH4_PCIMBR_MASK;
+	word = chan->resources[1].start & SH4_PCIMBR_MASK;
 	pr_debug("PCI: Setting upper bits of Memory window to 0x%x\n", word);
 	pci_write_reg(chan, word , SH4_PCIMBR);
 
 	/* Make sure the MSB's of IO window are set to access PCI space
 	 * correctly */
-	word = chan->io_resource->start & SH4_PCIIOBR_MASK;
+	word = chan->resources[0].start & SH4_PCIIOBR_MASK;
 	pr_debug("PCI: Setting upper bits of IO window to 0x%x\n", word);
 	pci_write_reg(chan, word, SH4_PCIIOBR);
 
@@ -159,13 +155,13 @@
 		return -1;
 
 	/* configure the wait control registers */
-	word = ctrl_inl(SH7751_WCR1);
+	word = __raw_readl(SH7751_WCR1);
 	pci_write_reg(chan, word, SH4_PCIWCR1);
-	word = ctrl_inl(SH7751_WCR2);
+	word = __raw_readl(SH7751_WCR2);
 	pci_write_reg(chan, word, SH4_PCIWCR2);
-	word = ctrl_inl(SH7751_WCR3);
+	word = __raw_readl(SH7751_WCR3);
 	pci_write_reg(chan, word, SH4_PCIWCR3);
-	word = ctrl_inl(SH7751_MCR);
+	word = __raw_readl(SH7751_MCR);
 	pci_write_reg(chan, word, SH4_PCIMCR);
 
 	/* NOTE: I'm ignoring the PCI error IRQs for now..
@@ -180,8 +176,6 @@
 	word = SH4_PCICR_PREFIX | SH4_PCICR_CFIN | SH4_PCICR_ARBM;
 	pci_write_reg(chan, word, SH4_PCICR);
 
-	register_pci_controller(chan);
-
-	return 0;
+	return register_pci_controller(chan);
 }
 arch_initcall(sh7751_pci_init);
diff --git a/arch/sh/drivers/pci/pci-sh7780.c b/arch/sh/drivers/pci/pci-sh7780.c
index 323b92d..ffdcbf1 100644
--- a/arch/sh/drivers/pci/pci-sh7780.c
+++ b/arch/sh/drivers/pci/pci-sh7780.c
@@ -1,7 +1,7 @@
 /*
  * Low-Level PCI Support for the SH7780
  *
- *  Copyright (C) 2005 - 2009  Paul Mundt
+ *  Copyright (C) 2005 - 2010  Paul Mundt
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
@@ -11,52 +11,240 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+#include <linux/irq.h>
 #include <linux/errno.h>
 #include <linux/delay.h>
+#include <linux/log2.h>
 #include "pci-sh4.h"
+#include <asm/mmu.h>
+#include <asm/sizes.h>
 
-static struct resource sh7785_io_resource = {
-	.name	= "SH7785_IO",
-	.start	= SH7780_PCI_IO_BASE,
-	.end	= SH7780_PCI_IO_BASE + SH7780_PCI_IO_SIZE - 1,
-	.flags	= IORESOURCE_IO
-};
-
-static struct resource sh7785_mem_resource = {
-	.name	= "SH7785_mem",
-	.start	= SH7780_PCI_MEMORY_BASE,
-	.end	= SH7780_PCI_MEMORY_BASE + SH7780_PCI_MEM_SIZE - 1,
-	.flags	= IORESOURCE_MEM
+static struct resource sh7785_pci_resources[] = {
+	{
+		.name	= "PCI IO",
+		.start	= 0x1000,
+		.end	= SZ_4M - 1,
+		.flags	= IORESOURCE_IO,
+	}, {
+		.name	= "PCI MEM 0",
+		.start	= 0xfd000000,
+		.end	= 0xfd000000 + SZ_16M - 1,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.name	= "PCI MEM 1",
+		.start	= 0x10000000,
+		.end	= 0x10000000 + SZ_64M - 1,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		/*
+		 * 32-bit only resources must be last.
+		 */
+		.name	= "PCI MEM 2",
+		.start	= 0xc0000000,
+		.end	= 0xc0000000 + SZ_512M - 1,
+		.flags	= IORESOURCE_MEM | IORESOURCE_MEM_32BIT,
+	},
 };
 
 static struct pci_channel sh7780_pci_controller = {
 	.pci_ops	= &sh4_pci_ops,
-	.mem_resource	= &sh7785_mem_resource,
-	.mem_offset	= 0x00000000,
-	.io_resource	= &sh7785_io_resource,
-	.io_offset	= 0x00000000,
-	.io_map_base	= SH7780_PCI_IO_BASE,
+	.resources	= sh7785_pci_resources,
+	.nr_resources	= ARRAY_SIZE(sh7785_pci_resources),
+	.io_offset	= 0,
+	.mem_offset	= 0,
+	.io_map_base	= 0xfe200000,
+	.serr_irq	= evt2irq(0xa00),
+	.err_irq	= evt2irq(0xaa0),
 };
 
-static struct sh4_pci_address_map sh7780_pci_map = {
-	.window0	= {
-#if defined(CONFIG_32BIT)
-		.base	= SH7780_32BIT_DDR_BASE_ADDR,
-		.size	= 0x40000000,
-#else
-		.base	= SH7780_CS0_BASE_ADDR,
-		.size	= 0x20000000,
-#endif
-	},
+struct pci_errors {
+	unsigned int	mask;
+	const char	*str;
+} pci_arbiter_errors[] = {
+	{ SH4_PCIAINT_MBKN,	"master broken" },
+	{ SH4_PCIAINT_TBTO,	"target bus time out" },
+	{ SH4_PCIAINT_MBTO,	"master bus time out" },
+	{ SH4_PCIAINT_TABT,	"target abort" },
+	{ SH4_PCIAINT_MABT,	"master abort" },
+	{ SH4_PCIAINT_RDPE,	"read data parity error" },
+	{ SH4_PCIAINT_WDPE,	"write data parity error" },
+}, pci_interrupt_errors[] = {
+	{ SH4_PCIINT_MLCK,	"master lock error" },
+	{ SH4_PCIINT_TABT,	"target-target abort" },
+	{ SH4_PCIINT_TRET,	"target retry time out" },
+	{ SH4_PCIINT_MFDE,	"master function disable erorr" },
+	{ SH4_PCIINT_PRTY,	"address parity error" },
+	{ SH4_PCIINT_SERR,	"SERR" },
+	{ SH4_PCIINT_TWDP,	"data parity error for target write" },
+	{ SH4_PCIINT_TRDP,	"PERR detected for target read" },
+	{ SH4_PCIINT_MTABT,	"target abort for master" },
+	{ SH4_PCIINT_MMABT,	"master abort for master" },
+	{ SH4_PCIINT_MWPD,	"master write data parity error" },
+	{ SH4_PCIINT_MRPD,	"master read data parity error" },
 };
 
+static irqreturn_t sh7780_pci_err_irq(int irq, void *dev_id)
+{
+	struct pci_channel *hose = dev_id;
+	unsigned long addr;
+	unsigned int status;
+	unsigned int cmd;
+	int i;
+
+	addr = __raw_readl(hose->reg_base + SH4_PCIALR);
+
+	/*
+	 * Handle status errors.
+	 */
+	status = __raw_readw(hose->reg_base + PCI_STATUS);
+	if (status & (PCI_STATUS_PARITY |
+		      PCI_STATUS_DETECTED_PARITY |
+		      PCI_STATUS_SIG_TARGET_ABORT |
+		      PCI_STATUS_REC_TARGET_ABORT |
+		      PCI_STATUS_REC_MASTER_ABORT)) {
+		cmd = pcibios_handle_status_errors(addr, status, hose);
+		if (likely(cmd))
+			__raw_writew(cmd, hose->reg_base + PCI_STATUS);
+	}
+
+	/*
+	 * Handle arbiter errors.
+	 */
+	status = __raw_readl(hose->reg_base + SH4_PCIAINT);
+	for (i = cmd = 0; i < ARRAY_SIZE(pci_arbiter_errors); i++) {
+		if (status & pci_arbiter_errors[i].mask) {
+			printk(KERN_DEBUG "PCI: %s, addr=%08lx\n",
+			       pci_arbiter_errors[i].str, addr);
+			cmd |= pci_arbiter_errors[i].mask;
+		}
+	}
+	__raw_writel(cmd, hose->reg_base + SH4_PCIAINT);
+
+	/*
+	 * Handle the remaining PCI errors.
+	 */
+	status = __raw_readl(hose->reg_base + SH4_PCIINT);
+	for (i = cmd = 0; i < ARRAY_SIZE(pci_interrupt_errors); i++) {
+		if (status & pci_interrupt_errors[i].mask) {
+			printk(KERN_DEBUG "PCI: %s, addr=%08lx\n",
+			       pci_interrupt_errors[i].str, addr);
+			cmd |= pci_interrupt_errors[i].mask;
+		}
+	}
+	__raw_writel(cmd, hose->reg_base + SH4_PCIINT);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t sh7780_pci_serr_irq(int irq, void *dev_id)
+{
+	struct pci_channel *hose = dev_id;
+
+	printk(KERN_DEBUG "PCI: system error received: ");
+	pcibios_report_status(PCI_STATUS_SIG_SYSTEM_ERROR, 1);
+	printk("\n");
+
+	/* Deassert SERR */
+	__raw_writel(SH4_PCIINTM_SDIM, hose->reg_base + SH4_PCIINTM);
+
+	/* Back off the IRQ for awhile */
+	disable_irq_nosync(irq);
+	hose->serr_timer.expires = jiffies + HZ;
+	add_timer(&hose->serr_timer);
+
+	return IRQ_HANDLED;
+}
+
+static int __init sh7780_pci_setup_irqs(struct pci_channel *hose)
+{
+	int ret;
+
+	/* Clear out PCI arbiter IRQs */
+	__raw_writel(0, hose->reg_base + SH4_PCIAINT);
+
+	/* Clear all error conditions */
+	__raw_writew(PCI_STATUS_DETECTED_PARITY  | \
+		     PCI_STATUS_SIG_SYSTEM_ERROR | \
+		     PCI_STATUS_REC_MASTER_ABORT | \
+		     PCI_STATUS_REC_TARGET_ABORT | \
+		     PCI_STATUS_SIG_TARGET_ABORT | \
+		     PCI_STATUS_PARITY, hose->reg_base + PCI_STATUS);
+
+	ret = request_irq(hose->serr_irq, sh7780_pci_serr_irq, IRQF_DISABLED,
+			  "PCI SERR interrupt", hose);
+	if (unlikely(ret)) {
+		printk(KERN_ERR "PCI: Failed hooking SERR IRQ\n");
+		return ret;
+	}
+
+	/*
+	 * The PCI ERR IRQ needs to be IRQF_SHARED since all of the power
+	 * down IRQ vectors are routed through the ERR IRQ vector. We
+	 * only request_irq() once as there is only a single masking
+	 * source for multiple events.
+	 */
+	ret = request_irq(hose->err_irq, sh7780_pci_err_irq, IRQF_SHARED,
+			  "PCI ERR interrupt", hose);
+	if (unlikely(ret)) {
+		free_irq(hose->serr_irq, hose);
+		return ret;
+	}
+
+	/* Unmask all of the arbiter IRQs. */
+	__raw_writel(SH4_PCIAINT_MBKN | SH4_PCIAINT_TBTO | SH4_PCIAINT_MBTO | \
+		     SH4_PCIAINT_TABT | SH4_PCIAINT_MABT | SH4_PCIAINT_RDPE | \
+		     SH4_PCIAINT_WDPE, hose->reg_base + SH4_PCIAINTM);
+
+	/* Unmask all of the PCI IRQs */
+	__raw_writel(SH4_PCIINTM_TTADIM  | SH4_PCIINTM_TMTOIM  | \
+		     SH4_PCIINTM_MDEIM   | SH4_PCIINTM_APEDIM  | \
+		     SH4_PCIINTM_SDIM    | SH4_PCIINTM_DPEITWM | \
+		     SH4_PCIINTM_PEDITRM | SH4_PCIINTM_TADIMM  | \
+		     SH4_PCIINTM_MADIMM  | SH4_PCIINTM_MWPDIM  | \
+		     SH4_PCIINTM_MRDPEIM, hose->reg_base + SH4_PCIINTM);
+
+	return ret;
+}
+
+static inline void __init sh7780_pci_teardown_irqs(struct pci_channel *hose)
+{
+	free_irq(hose->err_irq, hose);
+	free_irq(hose->serr_irq, hose);
+}
+
+static void __init sh7780_pci66_init(struct pci_channel *hose)
+{
+	unsigned int tmp;
+
+	if (!pci_is_66mhz_capable(hose, 0, 0))
+		return;
+
+	/* Enable register access */
+	tmp = __raw_readl(hose->reg_base + SH4_PCICR);
+	tmp |= SH4_PCICR_PREFIX;
+	__raw_writel(tmp, hose->reg_base + SH4_PCICR);
+
+	/* Enable 66MHz operation */
+	tmp = __raw_readw(hose->reg_base + PCI_STATUS);
+	tmp |= PCI_STATUS_66MHZ;
+	__raw_writew(tmp, hose->reg_base + PCI_STATUS);
+
+	/* Done */
+	tmp = __raw_readl(hose->reg_base + SH4_PCICR);
+	tmp |= SH4_PCICR_PREFIX | SH4_PCICR_CFIN;
+	__raw_writel(tmp, hose->reg_base + SH4_PCICR);
+}
+
 static int __init sh7780_pci_init(void)
 {
 	struct pci_channel *chan = &sh7780_pci_controller;
+	phys_addr_t memphys;
+	size_t memsize;
 	unsigned int id;
-	const char *type = NULL;
-	int ret;
-	u32 word;
+	const char *type;
+	int ret, i;
 
 	printk(KERN_NOTICE "PCI: Starting intialization.\n");
 
@@ -65,17 +253,28 @@
 	/* Enable CPU access to the PCIC registers. */
 	__raw_writel(PCIECR_ENBL, PCIECR);
 
-	id = __raw_readw(chan->reg_base + SH7780_PCIVID);
-	if (id != SH7780_VENDOR_ID) {
+	/* Reset */
+	__raw_writel(SH4_PCICR_PREFIX | SH4_PCICR_PRST,
+		     chan->reg_base + SH4_PCICR);
+
+	/*
+	 * Wait for it to come back up. The spec says to allow for up to
+	 * 1 second after toggling the reset pin, but in practice 100ms
+	 * is more than enough.
+	 */
+	mdelay(100);
+
+	id = __raw_readw(chan->reg_base + PCI_VENDOR_ID);
+	if (id != PCI_VENDOR_ID_RENESAS) {
 		printk(KERN_ERR "PCI: Unknown vendor ID 0x%04x.\n", id);
 		return -ENODEV;
 	}
 
-	id = __raw_readw(chan->reg_base + SH7780_PCIDID);
-	type = (id == SH7763_DEVICE_ID)	? "SH7763" :
-	       (id == SH7780_DEVICE_ID) ? "SH7780" :
-	       (id == SH7781_DEVICE_ID) ? "SH7781" :
-	       (id == SH7785_DEVICE_ID) ? "SH7785" :
+	id = __raw_readw(chan->reg_base + PCI_DEVICE_ID);
+	type = (id == PCI_DEVICE_ID_RENESAS_SH7763) ? "SH7763" :
+	       (id == PCI_DEVICE_ID_RENESAS_SH7780) ? "SH7780" :
+	       (id == PCI_DEVICE_ID_RENESAS_SH7781) ? "SH7781" :
+	       (id == PCI_DEVICE_ID_RENESAS_SH7785) ? "SH7785" :
 					  NULL;
 	if (unlikely(!type)) {
 		printk(KERN_ERR "PCI: Found an unsupported Renesas host "
@@ -85,62 +284,119 @@
 
 	printk(KERN_NOTICE "PCI: Found a Renesas %s host "
 	       "controller, revision %d.\n", type,
-	       __raw_readb(chan->reg_base + SH7780_PCIRID));
+	       __raw_readb(chan->reg_base + PCI_REVISION_ID));
 
-	if ((ret = sh4_pci_check_direct(chan)) != 0)
+	/*
+	 * Now throw it in to register initialization mode and
+	 * start the real work.
+	 */
+	__raw_writel(SH4_PCICR_PREFIX, chan->reg_base + SH4_PCICR);
+
+	memphys = __pa(memory_start);
+	memsize = roundup_pow_of_two(memory_end - memory_start);
+
+	/*
+	 * If there's more than 512MB of memory, we need to roll over to
+	 * LAR1/LSR1.
+	 */
+	if (memsize > SZ_512M) {
+		__raw_writel(memphys + SZ_512M, chan->reg_base + SH4_PCILAR1);
+		__raw_writel((((memsize - SZ_512M) - SZ_1M) & 0x1ff00000) | 1,
+			     chan->reg_base + SH4_PCILSR1);
+		memsize = SZ_512M;
+	} else {
+		/*
+		 * Otherwise just zero it out and disable it.
+		 */
+		__raw_writel(0, chan->reg_base + SH4_PCILAR1);
+		__raw_writel(0, chan->reg_base + SH4_PCILSR1);
+	}
+
+	/*
+	 * LAR0/LSR0 covers up to the first 512MB, which is enough to
+	 * cover all of lowmem on most platforms.
+	 */
+	__raw_writel(memphys, chan->reg_base + SH4_PCILAR0);
+	__raw_writel(((memsize - SZ_1M) & 0x1ff00000) | 1,
+		     chan->reg_base + SH4_PCILSR0);
+
+	/*
+	 * Hook up the ERR and SERR IRQs.
+	 */
+	ret = sh7780_pci_setup_irqs(chan);
+	if (unlikely(ret))
 		return ret;
 
 	/*
-	 * Set the class and sub-class codes.
+	 * Disable the cache snoop controller for non-coherent DMA.
 	 */
-	__raw_writeb(PCI_CLASS_BRIDGE_HOST >> 8,
-		     chan->reg_base + SH7780_PCIBCC);
-	__raw_writeb(PCI_CLASS_BRIDGE_HOST & 0xff,
-		     chan->reg_base + SH7780_PCISUB);
+	__raw_writel(0, chan->reg_base + SH7780_PCICSCR0);
+	__raw_writel(0, chan->reg_base + SH7780_PCICSAR0);
+	__raw_writel(0, chan->reg_base + SH7780_PCICSCR1);
+	__raw_writel(0, chan->reg_base + SH7780_PCICSAR1);
 
 	/*
-	 * Set IO and Mem windows to local address
-	 * Make PCI and local address the same for easy 1 to 1 mapping
+	 * Setup the memory BARs
 	 */
-	pci_write_reg(chan, sh7780_pci_map.window0.size - 0xfffff, SH4_PCILSR0);
-	/* Set the values on window 0 PCI config registers */
-	pci_write_reg(chan, sh7780_pci_map.window0.base, SH4_PCILAR0);
-	pci_write_reg(chan, sh7780_pci_map.window0.base, SH7780_PCIMBAR0);
+	for (i = 1; i < chan->nr_resources; i++) {
+		struct resource *res = chan->resources + i;
+		resource_size_t size;
 
-	pci_write_reg(chan, 0x0000380f, SH4_PCIAINTM);
+		if (unlikely(res->flags & IORESOURCE_IO))
+			continue;
 
-	/* Set up standard PCI config registers */
-	__raw_writew(0xFB00, chan->reg_base + SH7780_PCISTATUS);
-	__raw_writew(0x0047, chan->reg_base + SH7780_PCICMD);
-	__raw_writew(0x1912, chan->reg_base + SH7780_PCISVID);
-	__raw_writew(0x0001, chan->reg_base + SH7780_PCISID);
+		/*
+		 * Make sure we're in the right physical addressing mode
+		 * for dealing with the resource.
+		 */
+		if ((res->flags & IORESOURCE_MEM_32BIT) && __in_29bit_mode()) {
+			chan->nr_resources--;
+			continue;
+		}
 
-	__raw_writeb(0x00, chan->reg_base + SH7780_PCIPIF);
+		size = resource_size(res);
 
-	/* Apply any last-minute PCIC fixups */
-	pci_fixup_pcic(chan);
+		/*
+		 * The MBMR mask is calculated in units of 256kB, which
+		 * keeps things pretty simple.
+		 */
+		__raw_writel(((roundup_pow_of_two(size) / SZ_256K) - 1) << 18,
+			     chan->reg_base + SH7780_PCIMBMR(i - 1));
+		__raw_writel(res->start, chan->reg_base + SH7780_PCIMBR(i - 1));
+	}
 
-	pci_write_reg(chan, 0xfd000000, SH7780_PCIMBR0);
-	pci_write_reg(chan, 0x00fc0000, SH7780_PCIMBMR0);
+	/*
+	 * And I/O.
+	 */
+	__raw_writel(0, chan->reg_base + PCI_BASE_ADDRESS_0);
+	__raw_writel(0, chan->reg_base + SH7780_PCIIOBR);
+	__raw_writel(0, chan->reg_base + SH7780_PCIIOBMR);
 
-#ifdef CONFIG_32BIT
-	pci_write_reg(chan, 0xc0000000, SH7780_PCIMBR2);
-	pci_write_reg(chan, 0x20000000 - SH7780_PCI_IO_SIZE, SH7780_PCIMBMR2);
-#endif
+	__raw_writew(PCI_COMMAND_SERR   | PCI_COMMAND_WAIT   | \
+		     PCI_COMMAND_PARITY | PCI_COMMAND_MASTER | \
+		     PCI_COMMAND_MEMORY, chan->reg_base + PCI_COMMAND);
 
-	/* Set IOBR for windows containing area specified in pci.h */
-	pci_write_reg(chan, chan->io_resource->start & ~(SH7780_PCI_IO_SIZE-1),
-		      SH7780_PCIIOBR);
-	pci_write_reg(chan, ((SH7780_PCI_IO_SIZE-1) & (7<<18)),
-		      SH7780_PCIIOBMR);
+	/*
+	 * Initialization mode complete, release the control register and
+	 * enable round robin mode to stop device overruns/starvation.
+	 */
+	__raw_writel(SH4_PCICR_PREFIX | SH4_PCICR_CFIN | SH4_PCICR_FTO,
+		     chan->reg_base + SH4_PCICR);
 
-	/* SH7780 init done, set central function init complete */
-	/* use round robin mode to stop a device starving/overruning */
-	word = SH4_PCICR_PREFIX | SH4_PCICR_CFIN | SH4_PCICR_FTO;
-	pci_write_reg(chan, word, SH4_PCICR);
+	ret = register_pci_controller(chan);
+	if (unlikely(ret))
+		goto err;
 
-	register_pci_controller(chan);
+	sh7780_pci66_init(chan);
+
+	printk(KERN_NOTICE "PCI: Running at %dMHz.\n",
+	       (__raw_readw(chan->reg_base + PCI_STATUS) & PCI_STATUS_66MHZ) ?
+	       66 : 33);
 
 	return 0;
+
+err:
+	sh7780_pci_teardown_irqs(chan);
+	return ret;
 }
 arch_initcall(sh7780_pci_init);
diff --git a/arch/sh/drivers/pci/pci-sh7780.h b/arch/sh/drivers/pci/pci-sh7780.h
index 4a52478..205dcbe 100644
--- a/arch/sh/drivers/pci/pci-sh7780.h
+++ b/arch/sh/drivers/pci/pci-sh7780.h
@@ -12,12 +12,11 @@
 #ifndef _PCI_SH7780_H_
 #define _PCI_SH7780_H_
 
-/* Platform Specific Values */
-#define SH7780_VENDOR_ID	0x1912
-#define SH7781_DEVICE_ID	0x0001
-#define SH7780_DEVICE_ID	0x0002
-#define SH7763_DEVICE_ID	0x0004
-#define SH7785_DEVICE_ID	0x0007
+#define PCI_VENDOR_ID_RENESAS		0x1912
+#define PCI_DEVICE_ID_RENESAS_SH7781	0x0001
+#define PCI_DEVICE_ID_RENESAS_SH7780	0x0002
+#define PCI_DEVICE_ID_RENESAS_SH7763	0x0004
+#define PCI_DEVICE_ID_RENESAS_SH7785	0x0007
 
 /* SH7780 Control Registers */
 #define	PCIECR			0xFE000008
@@ -27,44 +26,9 @@
 #define SH7780_PCI_CONFIG_BASE	0xFD000000	/* Config space base addr */
 #define SH7780_PCI_CONFIG_SIZE	0x01000000	/* Config space size */
 
-#define SH7780_PCI_MEMORY_BASE	0xFD000000	/* Memory space base addr */
-#define SH7780_PCI_MEM_SIZE	0x01000000	/* Size of Memory window */
-
-#define SH7780_PCI_IO_BASE	0xFE200000	/* IO space base address */
-#define SH7780_PCI_IO_SIZE	0x00400000	/* Size of IO window */
-
 #define SH7780_PCIREG_BASE	0xFE040000	/* PCI regs base address */
 
 /* SH7780 PCI Config Registers */
-#define SH7780_PCIVID		0x000		/* Vendor ID */
-#define SH7780_PCIDID		0x002		/* Device ID */
-#define SH7780_PCICMD		0x004		/* Command */
-#define SH7780_PCISTATUS	0x006		/* Status */
-#define SH7780_PCIRID		0x008		/* Revision ID */
-#define SH7780_PCIPIF		0x009		/* Program Interface */
-#define SH7780_PCISUB		0x00a		/* Sub class code */
-#define SH7780_PCIBCC		0x00b		/* Base class code */
-#define SH7780_PCICLS		0x00c		/* Cache line size */
-#define SH7780_PCILTM		0x00d		/* latency timer */
-#define SH7780_PCIHDR		0x00e		/* Header type */
-#define SH7780_PCIBIST		0x00f		/* BIST */
-#define SH7780_PCIIBAR		0x010		/* IO Base address */
-#define SH7780_PCIMBAR0		0x014		/* Memory base address0 */
-#define SH7780_PCIMBAR1		0x018		/* Memory base address1 */
-#define SH7780_PCISVID		0x02c		/* Sub system vendor ID */
-#define SH7780_PCISID		0x02e		/* Sub system ID */
-#define SH7780_PCICP		0x034
-#define SH7780_PCIINTLINE	0x03c		/* Interrupt line */
-#define SH7780_PCIINTPIN	0x03d		/* Interrupt pin */
-#define SH7780_PCIMINGNT	0x03e		/* Minumum grand */
-#define SH7780_PCIMAXLAT	0x03f		/* Maxmum latency */
-#define SH7780_PCICID		0x040
-#define SH7780_PCINIP		0x041
-#define SH7780_PCIPMC		0x042
-#define SH7780_PCIPMCSR		0x044
-#define SH7780_PCIPMCSR_BSE	0x046
-#define SH7780_PCICDD		0x047
-
 #define SH7780_PCIIR		0x114		/* PCI Interrupt Register */
 #define SH7780_PCIIMR		0x118		/* PCI Interrupt Mask Register */
 #define SH7780_PCIAIR		0x11C		/* Error Address Register */
@@ -76,10 +40,8 @@
 #define SH7780_PCIPINT		0x1CC		/* Power Mgmnt Int. Register */
 #define SH7780_PCIPINTM		0x1D0		/* Power Mgmnt Mask Register */
 
-#define SH7780_PCIMBR0		0x1E0
-#define SH7780_PCIMBMR0		0x1E4
-#define SH7780_PCIMBR2		0x1F0
-#define SH7780_PCIMBMR2		0x1F4
+#define SH7780_PCIMBR(x)	(0x1E0 + ((x) * 8))
+#define SH7780_PCIMBMR(x)	(0x1E4 + ((x) * 8))
 #define SH7780_PCIIOBR		0x1F8
 #define SH7780_PCIIOBMR		0x1FC
 #define SH7780_PCICSCR0		0x210		/* Cache Snoop1 Cnt. Register */
@@ -87,16 +49,4 @@
 #define SH7780_PCICSAR0		0x218	/* Cache Snoop1 Addr. Register */
 #define SH7780_PCICSAR1		0x21C	/* Cache Snoop2 Addr. Register */
 
-/* General Memory Config Addresses */
-#define SH7780_CS0_BASE_ADDR	0x0
-#define SH7780_MEM_REGION_SIZE	0x04000000
-#define SH7780_CS1_BASE_ADDR	(SH7780_CS0_BASE_ADDR + SH7780_MEM_REGION_SIZE)
-#define SH7780_CS2_BASE_ADDR	(SH7780_CS1_BASE_ADDR + SH7780_MEM_REGION_SIZE)
-#define SH7780_CS3_BASE_ADDR	(SH7780_CS2_BASE_ADDR + SH7780_MEM_REGION_SIZE)
-#define SH7780_CS4_BASE_ADDR	(SH7780_CS3_BASE_ADDR + SH7780_MEM_REGION_SIZE)
-#define SH7780_CS5_BASE_ADDR	(SH7780_CS4_BASE_ADDR + SH7780_MEM_REGION_SIZE)
-#define SH7780_CS6_BASE_ADDR	(SH7780_CS5_BASE_ADDR + SH7780_MEM_REGION_SIZE)
-
-#define SH7780_32BIT_DDR_BASE_ADDR	0x40000000
-
 #endif /* _PCI_SH7780_H_ */
diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c
index 96213fd..953af13 100644
--- a/arch/sh/drivers/pci/pci.c
+++ b/arch/sh/drivers/pci/pci.c
@@ -33,15 +33,22 @@
 static void __devinit pcibios_scanbus(struct pci_channel *hose)
 {
 	static int next_busno;
+	static int need_domain_info;
 	struct pci_bus *bus;
 
 	bus = pci_scan_bus(next_busno, hose->pci_ops, hose);
+	hose->bus = bus;
+
+	need_domain_info = need_domain_info || hose->index;
+	hose->need_domain_info = need_domain_info;
 	if (bus) {
 		next_busno = bus->subordinate + 1;
 		/* Don't allow 8-bit bus number overflow inside the hose -
 		   reserve some space for bridges. */
-		if (next_busno > 224)
+		if (next_busno > 224) {
 			next_busno = 0;
+			need_domain_info = 1;
+		}
 
 		pci_bus_size_bridges(bus);
 		pci_bus_assign_resources(bus);
@@ -51,10 +58,21 @@
 
 static DEFINE_MUTEX(pci_scan_mutex);
 
-void __devinit register_pci_controller(struct pci_channel *hose)
+int __devinit register_pci_controller(struct pci_channel *hose)
 {
-	request_resource(&iomem_resource, hose->mem_resource);
-	request_resource(&ioport_resource, hose->io_resource);
+	int i;
+
+	for (i = 0; i < hose->nr_resources; i++) {
+		struct resource *res = hose->resources + i;
+
+		if (res->flags & IORESOURCE_IO) {
+			if (request_resource(&ioport_resource, res) < 0)
+				goto out;
+		} else {
+			if (request_resource(&iomem_resource, res) < 0)
+				goto out;
+		}
+	}
 
 	*hose_tail = hose;
 	hose_tail = &hose->next;
@@ -68,6 +86,11 @@
 	}
 
 	/*
+	 * Setup the ERR/PERR and SERR timers, if available.
+	 */
+	pcibios_enable_timers(hose);
+
+	/*
 	 * Scan the bus if it is register after the PCI subsystem
 	 * initialization.
 	 */
@@ -76,6 +99,15 @@
 		pcibios_scanbus(hose);
 		mutex_unlock(&pci_scan_mutex);
 	}
+
+	return 0;
+
+out:
+	for (--i; i >= 0; i--)
+		release_resource(&hose->resources[i]);
+
+	printk(KERN_WARNING "Skipping PCI bus scan due to resource conflict\n");
+	return -1;
 }
 
 static int __init pcibios_init(void)
@@ -127,11 +159,13 @@
 {
 	struct pci_dev *dev = bus->self;
 	struct list_head *ln;
-	struct pci_channel *chan = bus->sysdata;
+	struct pci_channel *hose = bus->sysdata;
 
 	if (!dev) {
-		bus->resource[0] = chan->io_resource;
-		bus->resource[1] = chan->mem_resource;
+		int i;
+
+		for (i = 0; i < hose->nr_resources; i++)
+			bus->resource[i] = hose->resources + i;
 	}
 
 	for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
@@ -152,30 +186,25 @@
 				resource_size_t size, resource_size_t align)
 {
 	struct pci_dev *dev = data;
-	struct pci_channel *chan = dev->sysdata;
+	struct pci_channel *hose = dev->sysdata;
 	resource_size_t start = res->start;
 
 	if (res->flags & IORESOURCE_IO) {
-		if (start < PCIBIOS_MIN_IO + chan->io_resource->start)
-			start = PCIBIOS_MIN_IO + chan->io_resource->start;
+		if (start < PCIBIOS_MIN_IO + hose->resources[0].start)
+			start = PCIBIOS_MIN_IO + hose->resources[0].start;
 
 		/*
                  * Put everything into 0x00-0xff region modulo 0x400.
 		 */
-		if (start & 0x300) {
+		if (start & 0x300)
 			start = (start + 0x3ff) & ~0x3ff;
-			res->start = start;
-		}
-	} else if (res->flags & IORESOURCE_MEM) {
-		if (start < PCIBIOS_MIN_MEM + chan->mem_resource->start)
-			start = PCIBIOS_MIN_MEM + chan->mem_resource->start;
 	}
 
 	return start;
 }
 
 void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
-			 struct resource *res)
+			     struct resource *res)
 {
 	struct pci_channel *hose = dev->sysdata;
 	unsigned long offset = 0;
@@ -189,9 +218,8 @@
 	region->end = res->end - offset;
 }
 
-void __devinit
-pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
-			struct pci_bus_region *region)
+void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+			     struct pci_bus_region *region)
 {
 	struct pci_channel *hose = dev->sysdata;
 	unsigned long offset = 0;
@@ -274,6 +302,86 @@
 	return str;
 }
 
+static void __init
+pcibios_bus_report_status_early(struct pci_channel *hose,
+				int top_bus, int current_bus,
+				unsigned int status_mask, int warn)
+{
+	unsigned int pci_devfn;
+	u16 status;
+	int ret;
+
+	for (pci_devfn = 0; pci_devfn < 0xff; pci_devfn++) {
+		if (PCI_FUNC(pci_devfn))
+			continue;
+		ret = early_read_config_word(hose, top_bus, current_bus,
+					     pci_devfn, PCI_STATUS, &status);
+		if (ret != PCIBIOS_SUCCESSFUL)
+			continue;
+		if (status == 0xffff)
+			continue;
+
+		early_write_config_word(hose, top_bus, current_bus,
+					pci_devfn, PCI_STATUS,
+					status & status_mask);
+		if (warn)
+			printk("(%02x:%02x: %04X) ", current_bus,
+			       pci_devfn, status);
+	}
+}
+
+/*
+ * We can't use pci_find_device() here since we are
+ * called from interrupt context.
+ */
+static void __init_refok
+pcibios_bus_report_status(struct pci_bus *bus, unsigned int status_mask,
+			  int warn)
+{
+	struct pci_dev *dev;
+
+	list_for_each_entry(dev, &bus->devices, bus_list) {
+		u16 status;
+
+		/*
+		 * ignore host bridge - we handle
+		 * that separately
+		 */
+		if (dev->bus->number == 0 && dev->devfn == 0)
+			continue;
+
+		pci_read_config_word(dev, PCI_STATUS, &status);
+		if (status == 0xffff)
+			continue;
+
+		if ((status & status_mask) == 0)
+			continue;
+
+		/* clear the status errors */
+		pci_write_config_word(dev, PCI_STATUS, status & status_mask);
+
+		if (warn)
+			printk("(%s: %04X) ", pci_name(dev), status);
+	}
+
+	list_for_each_entry(dev, &bus->devices, bus_list)
+		if (dev->subordinate)
+			pcibios_bus_report_status(dev->subordinate, status_mask, warn);
+}
+
+void __init_refok pcibios_report_status(unsigned int status_mask, int warn)
+{
+	struct pci_channel *hose;
+
+	for (hose = hose_head; hose; hose = hose->next) {
+		if (unlikely(!hose->bus))
+			pcibios_bus_report_status_early(hose, hose_head->index,
+					hose->index, status_mask, warn);
+		else
+			pcibios_bus_report_status(hose->bus, status_mask, warn);
+	}
+}
+
 int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
 			enum pci_mmap_state mmap_state, int write_combine)
 {
@@ -302,9 +410,15 @@
 {
 	struct pci_channel *chan = dev->sysdata;
 
-	if (!chan->io_map_base)
+	if (unlikely(!chan->io_map_base)) {
 		chan->io_map_base = generic_io_base;
 
+		if (pci_domains_supported)
+			panic("To avoid data corruption io_map_base MUST be "
+			      "set with multiple PCI domains.");
+	}
+
+
 	return (void __iomem *)(chan->io_map_base + port);
 }
 
@@ -321,20 +435,9 @@
 
 	if (flags & IORESOURCE_IO)
 		return ioport_map_pci(dev, start, len);
-
-	/*
-	 * Presently the IORESOURCE_MEM case is a bit special, most
-	 * SH7751 style PCI controllers have PCI memory at a fixed
-	 * location in the address space where no remapping is desired.
-	 * With the IORESOURCE_MEM case more care has to be taken
-	 * to inhibit page table mapping for legacy cores, but this is
-	 * punted off to __ioremap().
-	 *					-- PFM.
-	 */
 	if (flags & IORESOURCE_MEM) {
 		if (flags & IORESOURCE_CACHEABLE)
 			return ioremap(start, len);
-
 		return ioremap_nocache(start, len);
 	}
 
diff --git a/arch/sh/drivers/pci/pcie-sh7786.c b/arch/sh/drivers/pci/pcie-sh7786.c
index ac37ee8..ae91a2d 100644
--- a/arch/sh/drivers/pci/pcie-sh7786.c
+++ b/arch/sh/drivers/pci/pcie-sh7786.c
@@ -1,7 +1,7 @@
 /*
  * Low-Level PCI Express Support for the SH7786
  *
- *  Copyright (C) 2009  Paul Mundt
+ *  Copyright (C) 2009 - 2010  Paul Mundt
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
@@ -30,60 +30,84 @@
 	int (*port_init_hw)(struct sh7786_pcie_port *port);
 } *sh7786_pcie_hwops;
 
-static struct resource sh7786_pci_32bit_mem_resources[] = {
+static struct resource sh7786_pci0_resources[] = {
 	{
-		.name	= "pci0_mem",
-		.start	= SH4A_PCIMEM_BASEA,
-		.end	= SH4A_PCIMEM_BASEA + SZ_64M - 1,
+		.name	= "PCIe0 IO",
+		.start	= 0xfd000000,
+		.end	= 0xfd000000 + SZ_8M - 1,
+		.flags	= IORESOURCE_IO,
+	}, {
+		.name	= "PCIe0 MEM 0",
+		.start	= 0xc0000000,
+		.end	= 0xc0000000 + SZ_512M - 1,
+		.flags	= IORESOURCE_MEM | IORESOURCE_MEM_32BIT,
+	}, {
+		.name	= "PCIe0 MEM 1",
+		.start	= 0x10000000,
+		.end	= 0x10000000 + SZ_64M - 1,
 		.flags	= IORESOURCE_MEM,
 	}, {
-		.name	= "pci1_mem",
-		.start	= SH4A_PCIMEM_BASEA1,
-		.end	= SH4A_PCIMEM_BASEA1 + SZ_64M - 1,
-		.flags	= IORESOURCE_MEM,
-	}, {
-		.name	= "pci2_mem",
-		.start	= SH4A_PCIMEM_BASEA2,
-		.end	= SH4A_PCIMEM_BASEA2 + SZ_64M - 1,
-		.flags	= IORESOURCE_MEM,
+		.name	= "PCIe0 MEM 2",
+		.start	= 0xfe100000,
+		.end	= 0xfe100000 + SZ_1M - 1,
 	},
 };
 
-static struct resource sh7786_pci_29bit_mem_resource = {
-	.start	= SH4A_PCIMEM_BASE,
-	.end	= SH4A_PCIMEM_BASE + SZ_64M - 1,
-	.flags	= IORESOURCE_MEM,
+static struct resource sh7786_pci1_resources[] = {
+	{
+		.name	= "PCIe1 IO",
+		.start	= 0xfd800000,
+		.end	= 0xfd800000 + SZ_8M - 1,
+		.flags	= IORESOURCE_IO,
+	}, {
+		.name	= "PCIe1 MEM 0",
+		.start	= 0xa0000000,
+		.end	= 0xa0000000 + SZ_512M - 1,
+		.flags	= IORESOURCE_MEM | IORESOURCE_MEM_32BIT,
+	}, {
+		.name	= "PCIe1 MEM 1",
+		.start	= 0x30000000,
+		.end	= 0x30000000 + SZ_256M - 1,
+		.flags	= IORESOURCE_MEM | IORESOURCE_MEM_32BIT,
+	}, {
+		.name	= "PCIe1 MEM 2",
+		.start	= 0xfe300000,
+		.end	= 0xfe300000 + SZ_1M - 1,
+	},
 };
 
-static struct resource sh7786_pci_io_resources[] = {
+static struct resource sh7786_pci2_resources[] = {
 	{
-		.name	= "pci0_io",
-		.start	= SH4A_PCIIO_BASE,
-		.end	= SH4A_PCIIO_BASE + SZ_8M - 1,
-		.flags	= IORESOURCE_IO,
+		.name	= "PCIe2 IO",
+		.start	= 0xfc800000,
+		.end	= 0xfc800000 + SZ_4M - 1,
 	}, {
-		.name	= "pci1_io",
-		.start	= SH4A_PCIIO_BASE1,
-		.end	= SH4A_PCIIO_BASE1 + SZ_8M - 1,
-		.flags	= IORESOURCE_IO,
+		.name	= "PCIe2 MEM 0",
+		.start	= 0x80000000,
+		.end	= 0x80000000 + SZ_512M - 1,
+		.flags	= IORESOURCE_MEM | IORESOURCE_MEM_32BIT,
 	}, {
-		.name	= "pci2_io",
-		.start	= SH4A_PCIIO_BASE2,
-		.end	= SH4A_PCIIO_BASE2 + SZ_4M - 1,
-		.flags	= IORESOURCE_IO,
+		.name	= "PCIe2 MEM 1",
+		.start	= 0x20000000,
+		.end	= 0x20000000 + SZ_256M - 1,
+		.flags	= IORESOURCE_MEM | IORESOURCE_MEM_32BIT,
+	}, {
+		.name	= "PCIe2 MEM 2",
+		.start	= 0xfcd00000,
+		.end	= 0xfcd00000 + SZ_1M - 1,
 	},
 };
 
 extern struct pci_ops sh7786_pci_ops;
 
-#define DEFINE_CONTROLLER(start, idx)				\
-{								\
-	.pci_ops	= &sh7786_pci_ops,			\
-	.reg_base	= start,				\
-	/* mem_resource filled in at probe time */		\
-	.mem_offset	= 0,					\
-	.io_resource	= &sh7786_pci_io_resources[idx],	\
-	.io_offset	= 0,					\
+#define DEFINE_CONTROLLER(start, idx)					\
+{									\
+	.pci_ops	= &sh7786_pci_ops,				\
+	.resources	= sh7786_pci##idx##_resources,			\
+	.nr_resources	= ARRAY_SIZE(sh7786_pci##idx##_resources),	\
+	.reg_base	= start,					\
+	.mem_offset	= 0,						\
+	.io_offset	= 0,						\
 }
 
 static struct pci_channel sh7786_pci_channels[] = {
@@ -180,7 +204,9 @@
 {
 	struct pci_channel *chan = port->hose;
 	unsigned int data;
-	int ret;
+	phys_addr_t memphys;
+	size_t memsize;
+	int ret, i;
 
 	/* Begin initialization */
 	pci_write_reg(chan, 0, SH4A_PCIETCTLR);
@@ -203,15 +229,24 @@
 	data |= PCI_CAP_ID_EXP;
 	pci_write_reg(chan, data, SH4A_PCIEEXPCAP0);
 
-	/* Enable x4 link width and extended sync. */
+	/* Enable data link layer active state reporting */
+	pci_write_reg(chan, PCI_EXP_LNKCAP_DLLLARC, SH4A_PCIEEXPCAP3);
+
+	/* Enable extended sync and ASPM L0s support */
 	data = pci_read_reg(chan, SH4A_PCIEEXPCAP4);
-	data &= ~(PCI_EXP_LNKSTA_NLW << 16);
-	data |= (1 << 22) | PCI_EXP_LNKCTL_ES;
+	data &= ~PCI_EXP_LNKCTL_ASPMC;
+	data |= PCI_EXP_LNKCTL_ES | 1;
 	pci_write_reg(chan, data, SH4A_PCIEEXPCAP4);
 
+	/* Write out the physical slot number */
+	data = pci_read_reg(chan, SH4A_PCIEEXPCAP5);
+	data &= ~PCI_EXP_SLTCAP_PSN;
+	data |= (port->index + 1) << 19;
+	pci_write_reg(chan, data, SH4A_PCIEEXPCAP5);
+
 	/* Set the completion timer timeout to the maximum 32ms. */
 	data = pci_read_reg(chan, SH4A_PCIETLCTLR);
-	data &= ~0xffff;
+	data &= ~0x3f00;
 	data |= 0x32 << 8;
 	pci_write_reg(chan, data, SH4A_PCIETLCTLR);
 
@@ -224,6 +259,33 @@
 	data |= (0xff << 16);
 	pci_write_reg(chan, data, SH4A_PCIEMACCTLR);
 
+	memphys = __pa(memory_start);
+	memsize = roundup_pow_of_two(memory_end - memory_start);
+
+	/*
+	 * If there's more than 512MB of memory, we need to roll over to
+	 * LAR1/LAMR1.
+	 */
+	if (memsize > SZ_512M) {
+		__raw_writel(memphys + SZ_512M, chan->reg_base + SH4A_PCIELAR1);
+		__raw_writel(((memsize - SZ_512M) - SZ_256) | 1,
+			     chan->reg_base + SH4A_PCIELAMR1);
+		memsize = SZ_512M;
+	} else {
+		/*
+		 * Otherwise just zero it out and disable it.
+		 */
+		__raw_writel(0, chan->reg_base + SH4A_PCIELAR1);
+		__raw_writel(0, chan->reg_base + SH4A_PCIELAMR1);
+	}
+
+	/*
+	 * LAR0/LAMR0 covers up to the first 512MB, which is enough to
+	 * cover all of lowmem on most platforms.
+	 */
+	__raw_writel(memphys, chan->reg_base + SH4A_PCIELAR0);
+	__raw_writel((memsize - SZ_256) | 1, chan->reg_base + SH4A_PCIELAMR0);
+
 	/* Finish initialization */
 	data = pci_read_reg(chan, SH4A_PCIETCTLR);
 	data |= 0x1;
@@ -243,10 +305,14 @@
 	if (unlikely(ret != 0))
 		return -ENODEV;
 
-	pci_write_reg(chan, 0x00100007, SH4A_PCIEPCICONF1);
+	data = pci_read_reg(chan, SH4A_PCIEPCICONF1);
+	data &= ~(PCI_STATUS_DEVSEL_MASK << 16);
+	data |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
+		(PCI_STATUS_CAP_LIST | PCI_STATUS_DEVSEL_FAST) << 16;
+	pci_write_reg(chan, data, SH4A_PCIEPCICONF1);
+
 	pci_write_reg(chan, 0x80888000, SH4A_PCIETXVC0DCTLR);
 	pci_write_reg(chan, 0x00222000, SH4A_PCIERXVC0DCTLR);
-	pci_write_reg(chan, 0x000050A0, SH4A_PCIEEXPCAP2);
 
 	wmb();
 
@@ -254,15 +320,32 @@
 	printk(KERN_NOTICE "PCI: PCIe#%d link width %d\n",
 	       port->index, (data >> 20) & 0x3f);
 
-	pci_write_reg(chan, 0x007c0000, SH4A_PCIEPAMR0);
-	pci_write_reg(chan, 0x00000000, SH4A_PCIEPARH0);
-	pci_write_reg(chan, 0x00000000, SH4A_PCIEPARL0);
-	pci_write_reg(chan, 0x80000100, SH4A_PCIEPTCTLR0);
 
-	pci_write_reg(chan, 0x03fc0000, SH4A_PCIEPAMR2);
-	pci_write_reg(chan, 0x00000000, SH4A_PCIEPARH2);
-	pci_write_reg(chan, 0x00000000, SH4A_PCIEPARL2);
-	pci_write_reg(chan, 0x80000000, SH4A_PCIEPTCTLR2);
+	for (i = 0; i < chan->nr_resources; i++) {
+		struct resource *res = chan->resources + i;
+		resource_size_t size;
+		u32 enable_mask;
+
+		pci_write_reg(chan, 0x00000000, SH4A_PCIEPTCTLR(i));
+
+		size = resource_size(res);
+
+		/*
+		 * The PAMR mask is calculated in units of 256kB, which
+		 * keeps things pretty simple.
+		 */
+		__raw_writel(((roundup_pow_of_two(size) / SZ_256K) - 1) << 18,
+			     chan->reg_base + SH4A_PCIEPAMR(i));
+
+		pci_write_reg(chan, 0x00000000, SH4A_PCIEPARH(i));
+		pci_write_reg(chan, 0x00000000, SH4A_PCIEPARL(i));
+
+		enable_mask = MASK_PARE;
+		if (res->flags & IORESOURCE_IO)
+			enable_mask |= MASK_SPC;
+
+		pci_write_reg(chan, enable_mask, SH4A_PCIEPTCTLR(i));
+	}
 
 	return 0;
 }
@@ -296,9 +379,7 @@
 	if (unlikely(ret < 0))
 		return ret;
 
-	register_pci_controller(port->hose);
-
-	return 0;
+	return register_pci_controller(port->hose);
 }
 
 static struct sh7786_pcie_hwops sh7786_65nm_pcie_hwops __initdata = {
@@ -332,17 +413,7 @@
 
 		port->index		= i;
 		port->hose		= sh7786_pci_channels + i;
-		port->hose->io_map_base	= port->hose->io_resource->start;
-
-		/*
-		 * Check if we are booting in 29 or 32-bit mode
-		 *
-		 * 32-bit mode provides each controller with its own
-		 * memory window, while 29-bit mode uses a shared one.
-		 */
-		port->hose->mem_resource = test_mode_pin(MODE_PIN10) ?
-			&sh7786_pci_32bit_mem_resources[i] :
-			&sh7786_pci_29bit_mem_resource;
+		port->hose->io_map_base	= port->hose->resources[0].start;
 
 		ret |= sh7786_pcie_hwops->port_init_hw(port);
 	}
diff --git a/arch/sh/drivers/pci/pcie-sh7786.h b/arch/sh/drivers/pci/pcie-sh7786.h
index c655290..90a6992 100644
--- a/arch/sh/drivers/pci/pcie-sh7786.h
+++ b/arch/sh/drivers/pci/pcie-sh7786.h
@@ -30,47 +30,9 @@
  * for other(Max Payload Size=4096B,PCIIO_SIZE=8M)
  */
 
-/* PCI0-0: PCI I/O space */
-#define SH4A_PCIIO_BASE		0xFD000000	/* PCI I/O for controller 0 */
-#define SH4A_PCIIO_BASE1	0xFD800000	/* PCI I/O for controller 1 (Rev1.14)*/
-#define SH4A_PCIIO_BASE2	0xFC800000	/* PCI I/O for controller 2 (Rev1.171)*/
-
-#define SH4A_PCIIO_SIZE64	0x00010000	/* PLX allows only 64K */
-#define SH4A_PCIIO_SIZE		0x00800000	/* 8M */
-#define SH4A_PCIIO_SIZE2	0x00400000	/* 4M (Rev1.171)*/
-
-/* PCI0-1: PCI memory space 29-bit address */
-#define SH4A_PCIMEM_BASE	0x10000000
-#define SH4A_PCIMEM_SIZE	0x04000000	/* 64M */
-
-/* PCI0-2: PCI memory space 32-bit address */
-#define SH4A_PCIMEM_BASEA	0xC0000000	/*  for controller 0 */
-#define SH4A_PCIMEM_BASEA1	0xA0000000	/*  for controller 1 (Rev1.14)*/
-#define SH4A_PCIMEM_BASEA2	0x80000000	/*  for controller 2 (Rev1.171)*/
-#define SH4A_PCIMEM_SIZEA	0x20000000	/* 512M */
-
 /* PCI0: PCI memory target transfer 32-bit address translation value(Rev1.11T)*/
 #define SH4A_PCIBMSTR_TRANSLATION	0x20000000
 
-#define SH4A_PCI_DEVICE_ID		0x0002
-#define SH4A_PCI_VENDOR_ID		0x1912
-
-// PCI compatible 000-03f
-#define PCI_CMD		0x004
-#define PCI_RID		0x008
-#define PCI_IBAR	0x010
-#define PCI_MBAR0	0x014
-#define PCI_MBAR1	0x018
-
-/* PCI power management/MSI/capablity 040-0ff */
-/* PCIE extended 100-fff */
-
-/* SH7786 device identification */	// Rev1.171
-#define SH4A_PVR		(0xFF000030)
-#define SH4A_PVR_SHX3		(0x10400000)
-#define SH4A_PRR		(0xFF000044)
-#define SH4A_PRR_SH7786		(0x00000400)	// Rev1.171
-
 /*	SPVCR0		*/
 #define	SH4A_PCIEVCR0		(0x000000)	/* R - 0x0000 0000 32 */
 #define		BITS_TOP_MB	(24)
@@ -350,23 +312,23 @@
 #define	SH4A_PCIECSAR5		(0x0202B4)	/* R/W R/W 0x0000 0000 32 */
 #define	SH4A_PCIESTCTLR5	(0x0202B8)	/* R/W R/W 0x0000 0000 32 */
 
-/*	PCIEPARL0	*/
-#define	SH4A_PCIEPARL0		(0x020400)	/* R/W R/W 0x0000 0000 32 */
+/*	PCIEPARL	*/
+#define	SH4A_PCIEPARL(x)	(0x020400 + ((x) * 0x20)) /* R/W R/W 0x0000 0000 32 */
 #define		BITS_PAL	(18)
 #define		MASK_PAL	(0x3fff<<BITS_PAL)
 
-/*	PCIEPARH0	*/
-#define	SH4A_PCIEPARH0		(0x020404)	/* R/W R/W 0x0000 0000 32 */
+/*	PCIEPARH	*/
+#define	SH4A_PCIEPARH(x)	(0x020404 + ((x) * 0x20)) /* R/W R/W 0x0000 0000 32 */
 #define		BITS_PAH	(0)
 #define		MASK_PAH	(0xffffffff<<BITS_PAH)
 
-/*	PCIEPAMR0	 */
-#define	SH4A_PCIEPAMR0		(0x020408)	/* R/W R/W 0x0000 0000 32 */
+/*	PCIEPAMR	 */
+#define	SH4A_PCIEPAMR(x)	(0x020408 + ((x) * 0x20)) /* R/W R/W 0x0000 0000 32 */
 #define		BITS_PAM	(18)
 #define		MASK_PAM	(0x3fff<<BITS_PAM)
 
-/*	PCIEPTCTLR0	*/
-#define	SH4A_PCIEPTCTLR0	(0x02040C)	/* R/W R/W 0x0000 0000 32 */
+/*	PCIEPTCTLR	*/
+#define SH4A_PCIEPTCTLR(x)	(0x02040C + ((x) * 0x20))
 #define		BITS_PARE	(31)
 #define		MASK_PARE	(0x1<<BITS_PARE)
 #define		BITS_TC		(20)
@@ -378,26 +340,6 @@
 #define		BITS_SPC	(8)
 #define		MASK_SPC	(0x1<<BITS_SPC)
 
-#define	SH4A_PCIEPARL1		(0x020420)	/* R/W R/W 0x0000 0000 32 */
-#define	SH4A_PCIEPARH1		(0x020424)	/* R/W R/W 0x0000 0000 32 */
-#define	SH4A_PCIEPAMR1		(0x020428)	/* R/W R/W 0x0000 0000 32 */
-#define	SH4A_PCIEPTCTLR1	(0x02042C)	/* R/W R/W 0x0000 0000 32 */
-#define	SH4A_PCIEPARL2		(0x020440)	/* R/W R/W 0x0000 0000 32 */
-#define	SH4A_PCIEPARH2		(0x020444)	/* R/W R/W 0x0000 0000 32 */
-#define	SH4A_PCIEPAMR2		(0x020448)	/* R/W R/W 0x0000 0000 32 */
-#define	SH4A_PCIEPTCTLR2	(0x02044C)	/* R/W R/W 0x0000 0000 32 */
-#define	SH4A_PCIEPARL3		(0x020460)	/* R/W R/W 0x0000 0000 32 */
-#define	SH4A_PCIEPARH3		(0x020464)	/* R/W R/W 0x0000 0000 32 */
-#define	SH4A_PCIEPAMR3		(0x020468)	/* R/W R/W 0x0000 0000 32 */
-#define	SH4A_PCIEPTCTLR3	(0x02046C)	/* R/W R/W 0x0000 0000 32 */
-#define	SH4A_PCIEPARL4		(0x020480)	/* R/W R/W 0x0000 0000 32 */
-#define	SH4A_PCIEPARH4		(0x020484)	/* R/W R/W 0x0000 0000 32 */
-#define	SH4A_PCIEPAMR4		(0x020488)	/* R/W R/W 0x0000 0000 32 */
-#define	SH4A_PCIEPTCTLR4	(0x02048C)	/* R/W R/W 0x0000 0000 32 */
-#define	SH4A_PCIEPARL5		(0x0204A0)	/* R/W R/W 0x0000 0000 32 */
-#define	SH4A_PCIEPARH5		(0x0204A4)	/* R/W R/W 0x0000 0000 32 */
-#define	SH4A_PCIEPAMR5		(0x0204A8)	/* R/W R/W 0x0000 0000 32 */
-#define	SH4A_PCIEPTCTLR5	(0x0204AC)	/* R/W R/W 0x0000 0000 32 */
 #define	SH4A_PCIEDMAOR		(0x021000)	/* R/W R/W 0x0000 0000 32 */
 #define	SH4A_PCIEDMSAR0		(0x021100)	/* R/W R/W 0x0000 0000 32 */
 #define	SH4A_PCIEDMSAHR0	(0x021104)	/* R/W R/W 0x0000 0000 32 */
diff --git a/arch/sh/drivers/superhyway/ops-sh4-202.c b/arch/sh/drivers/superhyway/ops-sh4-202.c
index 3b14bf8..6da62e9 100644
--- a/arch/sh/drivers/superhyway/ops-sh4-202.c
+++ b/arch/sh/drivers/superhyway/ops-sh4-202.c
@@ -134,8 +134,8 @@
 	 *
 	 * Do not trust the documentation, for it is evil.
 	 */
-	vcrh = ctrl_inl(base);
-	vcrl = ctrl_inl(base + sizeof(u32));
+	vcrh = __raw_readl(base);
+	vcrl = __raw_readl(base + sizeof(u32));
 
 	tmp = ((u64)vcrh << 32) | vcrl;
 	memcpy(vcr, &tmp, sizeof(u64));
@@ -147,8 +147,8 @@
 {
 	u64 tmp = *(u64 *)&vcr;
 
-	ctrl_outl((tmp >> 32) & 0xffffffff, base);
-	ctrl_outl(tmp & 0xffffffff, base + sizeof(u32));
+	__raw_writel((tmp >> 32) & 0xffffffff, base);
+	__raw_writel(tmp & 0xffffffff, base + sizeof(u32));
 
 	return 0;
 }
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
index e121c30..46cb934 100644
--- a/arch/sh/include/asm/Kbuild
+++ b/arch/sh/include/asm/Kbuild
@@ -1,6 +1,8 @@
 include include/asm-generic/Kbuild.asm
 
-header-y += cachectl.h cpu-features.h
+header-y += cachectl.h
+header-y += cpu-features.h
+header-y += hw_breakpoint.h
 
 unifdef-y += unistd_32.h
 unifdef-y += unistd_64.h
diff --git a/arch/sh/include/asm/addrspace.h b/arch/sh/include/asm/addrspace.h
index 99d6b3e..446b383 100644
--- a/arch/sh/include/asm/addrspace.h
+++ b/arch/sh/include/asm/addrspace.h
@@ -28,7 +28,7 @@
 /* Returns the privileged segment base of a given address  */
 #define PXSEG(a)	(((unsigned long)(a)) & 0xe0000000)
 
-#if defined(CONFIG_29BIT) || defined(CONFIG_PMB_FIXED)
+#ifdef CONFIG_29BIT
 /*
  * Map an address to a certain privileged segment
  */
@@ -40,7 +40,15 @@
 	((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | P3SEG))
 #define P4SEGADDR(a)	\
 	((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | P4SEG))
-#endif /* 29BIT || PMB_FIXED */
+#else
+/*
+ * These will never work in 32-bit, don't even bother.
+ */
+#define P1SEGADDR(a)	__futile_remapping_attempt
+#define P2SEGADDR(a)	__futile_remapping_attempt
+#define P3SEGADDR(a)	__futile_remapping_attempt
+#define P4SEGADDR(a)	__futile_remapping_attempt
+#endif
 #endif /* P1SEG */
 
 /* Check if an address can be reached in 29 bits */
@@ -57,11 +65,5 @@
 #define P3_ADDR_MAX		P4SEG
 #endif
 
-#ifndef __ASSEMBLY__
-#ifdef CONFIG_PMB
-extern int __in_29bit_mode(void);
-#endif /* CONFIG_PMB */
-#endif /* __ASSEMBLY__ */
-
 #endif /* __KERNEL__ */
 #endif /* __ASM_SH_ADDRSPACE_H */
diff --git a/arch/sh/include/asm/alignment.h b/arch/sh/include/asm/alignment.h
new file mode 100644
index 0000000..b12efec
--- /dev/null
+++ b/arch/sh/include/asm/alignment.h
@@ -0,0 +1,21 @@
+#ifndef __ASM_SH_ALIGNMENT_H
+#define __ASM_SH_ALIGNMENT_H
+
+#include <linux/types.h>
+
+extern void inc_unaligned_byte_access(void);
+extern void inc_unaligned_word_access(void);
+extern void inc_unaligned_dword_access(void);
+extern void inc_unaligned_multi_access(void);
+extern void inc_unaligned_user_access(void);
+extern void inc_unaligned_kernel_access(void);
+
+#define UM_WARN		(1 << 0)
+#define UM_FIXUP	(1 << 1)
+#define UM_SIGNAL	(1 << 2)
+
+extern unsigned int unaligned_user_action(void);
+
+extern void unaligned_fixups_notify(struct task_struct *, insn_size_t, struct pt_regs *);
+
+#endif /* __ASM_SH_ALIGNMENT_H */
diff --git a/arch/sh/include/asm/atomic-grb.h b/arch/sh/include/asm/atomic-grb.h
index 4c5b7db..a273c88 100644
--- a/arch/sh/include/asm/atomic-grb.h
+++ b/arch/sh/include/asm/atomic-grb.h
@@ -120,50 +120,4 @@
 		: "memory" , "r0", "r1");
 }
 
-static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
-{
-	int ret;
-
-	__asm__ __volatile__ (
-		"   .align 2		\n\t"
-		"   mova     1f,  r0	\n\t"
-		"   nop			\n\t"
-		"   mov     r15,  r1	\n\t"
-		"   mov    #-8,  r15	\n\t"
-		"   mov.l   @%1,  %0	\n\t"
-		"   cmp/eq   %2,  %0	\n\t"
-		"   bf	     1f		\n\t"
-		"   mov.l    %3, @%1	\n\t"
-		"1: mov      r1,  r15	\n\t"
-		: "=&r" (ret)
-		: "r" (v), "r" (old), "r" (new)
-		: "memory" , "r0", "r1" , "t");
-
-	return ret;
-}
-
-static inline int atomic_add_unless(atomic_t *v, int a, int u)
-{
-	int ret;
-	unsigned long tmp;
-
-	__asm__ __volatile__ (
-		"   .align 2		\n\t"
-		"   mova    1f,   r0	\n\t"
-		"   nop			\n\t"
-		"   mov    r15,   r1	\n\t"
-		"   mov    #-12,  r15	\n\t"
-		"   mov.l  @%2,   %1	\n\t"
-		"   mov	    %1,   %0    \n\t"
-		"   cmp/eq  %4,   %0	\n\t"
-		"   bt/s    1f		\n\t"
-		"    add    %3,   %1	\n\t"
-		"   mov.l   %1,  @%2	\n\t"
-		"1: mov     r1,   r15	\n\t"
-		: "=&r" (ret), "=&r" (tmp)
-		: "r" (v), "r" (a), "r" (u)
-		: "memory" , "r0", "r1" , "t");
-
-	return ret != u;
-}
 #endif /* __ASM_SH_ATOMIC_GRB_H */
diff --git a/arch/sh/include/asm/atomic-llsc.h b/arch/sh/include/asm/atomic-llsc.h
index b040e1e..4b00b78 100644
--- a/arch/sh/include/asm/atomic-llsc.h
+++ b/arch/sh/include/asm/atomic-llsc.h
@@ -104,31 +104,4 @@
 	: "t");
 }
 
-#define atomic_cmpxchg(v, o, n) (cmpxchg(&((v)->counter), (o), (n)))
-
-/**
- * atomic_add_unless - add unless the number is a given value
- * @v: pointer of type atomic_t
- * @a: the amount to add to v...
- * @u: ...unless v is equal to u.
- *
- * Atomically adds @a to @v, so long as it was not @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
- */
-static inline int atomic_add_unless(atomic_t *v, int a, int u)
-{
-	int c, old;
-	c = atomic_read(v);
-	for (;;) {
-		if (unlikely(c == (u)))
-			break;
-		old = atomic_cmpxchg((v), c, c + (a));
-		if (likely(old == c))
-			break;
-		c = old;
-	}
-
-	return c != (u);
-}
-
 #endif /* __ASM_SH_ATOMIC_LLSC_H */
diff --git a/arch/sh/include/asm/atomic.h b/arch/sh/include/asm/atomic.h
index b16388d..275a448 100644
--- a/arch/sh/include/asm/atomic.h
+++ b/arch/sh/include/asm/atomic.h
@@ -25,58 +25,43 @@
 #endif
 
 #define atomic_add_negative(a, v)	(atomic_add_return((a), (v)) < 0)
+#define atomic_dec_return(v)		atomic_sub_return(1, (v))
+#define atomic_inc_return(v)		atomic_add_return(1, (v))
+#define atomic_inc_and_test(v)		(atomic_inc_return(v) == 0)
+#define atomic_sub_and_test(i,v)	(atomic_sub_return((i), (v)) == 0)
+#define atomic_dec_and_test(v)		(atomic_sub_return(1, (v)) == 0)
+#define atomic_inc_not_zero(v)		atomic_add_unless((v), 1, 0)
 
-#define atomic_dec_return(v) atomic_sub_return(1,(v))
-#define atomic_inc_return(v) atomic_add_return(1,(v))
+#define atomic_inc(v)			atomic_add(1, (v))
+#define atomic_dec(v)			atomic_sub(1, (v))
 
-/*
- * atomic_inc_and_test - increment and test
+#define atomic_xchg(v, new)		(xchg(&((v)->counter), new))
+#define atomic_cmpxchg(v, o, n)		(cmpxchg(&((v)->counter), (o), (n)))
+
+/**
+ * atomic_add_unless - add unless the number is a given value
  * @v: pointer of type atomic_t
+ * @a: the amount to add to v...
+ * @u: ...unless v is equal to u.
  *
- * Atomically increments @v by 1
- * and returns true if the result is zero, or false for all
- * other cases.
+ * Atomically adds @a to @v, so long as it was not @u.
+ * Returns non-zero if @v was not @u, and zero otherwise.
  */
-#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)
-
-#define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0)
-#define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
-
-#define atomic_inc(v) atomic_add(1,(v))
-#define atomic_dec(v) atomic_sub(1,(v))
-
-#if !defined(CONFIG_GUSA_RB) && !defined(CONFIG_CPU_SH4A)
-static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
-{
-	int ret;
-	unsigned long flags;
-
-	local_irq_save(flags);
-	ret = v->counter;
-	if (likely(ret == old))
-		v->counter = new;
-	local_irq_restore(flags);
-
-	return ret;
-}
-
 static inline int atomic_add_unless(atomic_t *v, int a, int u)
 {
-	int ret;
-	unsigned long flags;
+	int c, old;
+	c = atomic_read(v);
+	for (;;) {
+		if (unlikely(c == (u)))
+			break;
+		old = atomic_cmpxchg((v), c, c + (a));
+		if (likely(old == c))
+			break;
+		c = old;
+	}
 
-	local_irq_save(flags);
-	ret = v->counter;
-	if (ret != u)
-		v->counter += a;
-	local_irq_restore(flags);
-
-	return ret != u;
+	return c != (u);
 }
-#endif /* !CONFIG_GUSA_RB && !CONFIG_CPU_SH4A */
-
-#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
 #define smp_mb__before_atomic_dec()	smp_mb()
 #define smp_mb__after_atomic_dec()	smp_mb()
diff --git a/arch/sh/include/asm/clock.h b/arch/sh/include/asm/clock.h
index 9fe7d7f..11da4c5 100644
--- a/arch/sh/include/asm/clock.h
+++ b/arch/sh/include/asm/clock.h
@@ -146,8 +146,17 @@
 	.flags = _flags,						\
 }
 
+struct clk_div4_table {
+	struct clk_div_mult_table *div_mult_table;
+	void (*kick)(struct clk *clk);
+};
+
 int sh_clk_div4_register(struct clk *clks, int nr,
-			 struct clk_div_mult_table *table);
+			 struct clk_div4_table *table);
+int sh_clk_div4_enable_register(struct clk *clks, int nr,
+			 struct clk_div4_table *table);
+int sh_clk_div4_reparent_register(struct clk *clks, int nr,
+			 struct clk_div4_table *table);
 
 #define SH_CLK_DIV6(_name, _parent, _reg, _flags)	\
 {							\
diff --git a/arch/sh/include/asm/cmpxchg-grb.h b/arch/sh/include/asm/cmpxchg-grb.h
index e2681ab..4676bf5 100644
--- a/arch/sh/include/asm/cmpxchg-grb.h
+++ b/arch/sh/include/asm/cmpxchg-grb.h
@@ -57,11 +57,10 @@
 		"   mov.l  @%1,   %0      \n\t" /* load  old value */
 		"   cmp/eq  %0,   %2      \n\t"
 		"   bf            1f      \n\t" /* if not equal */
-		"   mov.l   %2,   @%1     \n\t" /* store new value */
+		"   mov.l   %3,   @%1     \n\t" /* store new value */
 		"1: mov     r1,   r15     \n\t" /* LOGOUT */
-		: "=&r" (retval),
-		  "+r"  (m)
-		: "r"   (new)
+		: "=&r" (retval)
+		:  "r"  (m), "r"  (old), "r"  (new)
 		: "memory" , "r0", "r1", "t");
 
 	return retval;
diff --git a/arch/sh/include/asm/dma-mapping.h b/arch/sh/include/asm/dma-mapping.h
index 87ced13..bea3337 100644
--- a/arch/sh/include/asm/dma-mapping.h
+++ b/arch/sh/include/asm/dma-mapping.h
@@ -89,8 +89,6 @@
 {
 	struct dma_map_ops *ops = get_dma_ops(dev);
 
-	WARN_ON(irqs_disabled());	/* for portability */
-
 	if (dma_release_from_coherent(dev, get_order(size), vaddr))
 		return;
 
diff --git a/arch/sh/include/asm/dma-sh.h b/arch/sh/include/asm/dma-sh.h
index 78eed3e0..e934a2e 100644
--- a/arch/sh/include/asm/dma-sh.h
+++ b/arch/sh/include/asm/dma-sh.h
@@ -20,14 +20,14 @@
     defined(CONFIG_CPU_SUBTYPE_SH7780)	|| \
     defined(CONFIG_CPU_SUBTYPE_SH7785)
 #define dmaor_read_reg(n) \
-    (n ? ctrl_inw(SH_DMAC_BASE1 + DMAOR) \
-	: ctrl_inw(SH_DMAC_BASE0 + DMAOR))
+    (n ? __raw_readw(SH_DMAC_BASE1 + DMAOR) \
+	: __raw_readw(SH_DMAC_BASE0 + DMAOR))
 #define dmaor_write_reg(n, data) \
-    (n ? ctrl_outw(data, SH_DMAC_BASE1 + DMAOR) \
-    : ctrl_outw(data, SH_DMAC_BASE0 + DMAOR))
+    (n ? __raw_writew(data, SH_DMAC_BASE1 + DMAOR) \
+    : __raw_writew(data, SH_DMAC_BASE0 + DMAOR))
 #else /* Other CPU */
-#define dmaor_read_reg(n) ctrl_inw(SH_DMAC_BASE0 + DMAOR)
-#define dmaor_write_reg(n, data) ctrl_outw(data, SH_DMAC_BASE0 + DMAOR)
+#define dmaor_read_reg(n) __raw_readw(SH_DMAC_BASE0 + DMAOR)
+#define dmaor_write_reg(n, data) __raw_writew(data, SH_DMAC_BASE0 + DMAOR)
 #endif
 
 static int dmte_irq_map[] __maybe_unused = {
@@ -64,8 +64,10 @@
 #define ACK_L	0x00010000
 #define DM_INC	0x00004000
 #define DM_DEC	0x00008000
+#define DM_FIX	0x0000c000
 #define SM_INC	0x00001000
 #define SM_DEC	0x00002000
+#define SM_FIX	0x00003000
 #define RS_IN	0x00000200
 #define RS_OUT	0x00000300
 #define TS_BLK	0x00000040
@@ -83,7 +85,7 @@
  * Define the default configuration for dual address memory-memory transfer.
  * The 0x400 value represents auto-request, external->external.
  */
-#define RS_DUAL	(DM_INC | SM_INC | 0x400 | TS_32)
+#define RS_DUAL	(DM_INC | SM_INC | 0x400 | TS_INDEX2VAL(XMIT_SZ_32BIT))
 
 /* DMA base address */
 static u32 dma_base_addr[] __maybe_unused = {
@@ -123,10 +125,47 @@
  */
 #define SHDMA_MIX_IRQ	(1 << 1)
 #define SHDMA_DMAOR1	(1 << 2)
-#define SHDMA_DMAE1		(1 << 3)
+#define SHDMA_DMAE1	(1 << 3)
+
+enum sh_dmae_slave_chan_id {
+	SHDMA_SLAVE_SCIF0_TX,
+	SHDMA_SLAVE_SCIF0_RX,
+	SHDMA_SLAVE_SCIF1_TX,
+	SHDMA_SLAVE_SCIF1_RX,
+	SHDMA_SLAVE_SCIF2_TX,
+	SHDMA_SLAVE_SCIF2_RX,
+	SHDMA_SLAVE_SCIF3_TX,
+	SHDMA_SLAVE_SCIF3_RX,
+	SHDMA_SLAVE_SCIF4_TX,
+	SHDMA_SLAVE_SCIF4_RX,
+	SHDMA_SLAVE_SCIF5_TX,
+	SHDMA_SLAVE_SCIF5_RX,
+	SHDMA_SLAVE_SIUA_TX,
+	SHDMA_SLAVE_SIUA_RX,
+	SHDMA_SLAVE_SIUB_TX,
+	SHDMA_SLAVE_SIUB_RX,
+	SHDMA_SLAVE_NUMBER,	/* Must stay last */
+};
+
+struct sh_dmae_slave_config {
+	enum sh_dmae_slave_chan_id	slave_id;
+	dma_addr_t			addr;
+	u32				chcr;
+	char				mid_rid;
+};
 
 struct sh_dmae_pdata {
 	unsigned int mode;
+	struct sh_dmae_slave_config *config;
+	int config_num;
+};
+
+struct device;
+
+struct sh_dmae_slave {
+	enum sh_dmae_slave_chan_id	slave_id; /* Set by the platform */
+	struct device			*dma_dev; /* Set by the platform */
+	struct sh_dmae_slave_config	*config;  /* Set by the driver */
 };
 
 #endif /* __DMA_SH_H */
diff --git a/arch/sh/include/asm/dwarf.h b/arch/sh/include/asm/dwarf.h
index bdccbbf..d62abd1 100644
--- a/arch/sh/include/asm/dwarf.h
+++ b/arch/sh/include/asm/dwarf.h
@@ -243,16 +243,13 @@
 
 	unsigned long cie_pointer;
 
-	struct list_head link;
-
 	unsigned long flags;
 #define DWARF_CIE_Z_AUGMENTATION	(1 << 0)
 
-	/*
-	 * 'mod' will be non-NULL if this CIE came from a module's
-	 * .eh_frame section.
-	 */
-	struct module *mod;
+	/* linked-list entry if this CIE is from a module */
+	struct list_head link;
+
+	struct rb_node node;
 };
 
 /**
@@ -266,13 +263,11 @@
 	unsigned long address_range;
 	unsigned char *instructions;
 	unsigned char *end;
+
+	/* linked-list entry if this FDE is from a module */
 	struct list_head link;
 
-	/*
-	 * 'mod' will be non-NULL if this FDE came from a module's
-	 * .eh_frame section.
-	 */
-	struct module *mod;
+	struct rb_node node;
 };
 
 /**
diff --git a/arch/sh/include/asm/fixmap.h b/arch/sh/include/asm/fixmap.h
index 5ac1e40..6e7cea4 100644
--- a/arch/sh/include/asm/fixmap.h
+++ b/arch/sh/include/asm/fixmap.h
@@ -55,16 +55,29 @@
 #define FIX_N_COLOURS 8
 	FIX_CMAP_BEGIN,
 	FIX_CMAP_END = FIX_CMAP_BEGIN + (FIX_N_COLOURS * NR_CPUS) - 1,
-	FIX_UNCACHED,
+
 #ifdef CONFIG_HIGHMEM
 	FIX_KMAP_BEGIN,	/* reserved pte's for temporary kernel mappings */
 	FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
 #endif
+
+#ifdef CONFIG_IOREMAP_FIXED
+	/*
+	 * FIX_IOREMAP entries are useful for mapping physical address
+	 * space before ioremap() is useable, e.g. really early in boot
+	 * before kmalloc() is working.
+	 */
+#define FIX_N_IOREMAPS	32
+	FIX_IOREMAP_BEGIN,
+	FIX_IOREMAP_END = FIX_IOREMAP_BEGIN + FIX_N_IOREMAPS,
+#endif
+
 	__end_of_fixed_addresses
 };
 
 extern void __set_fixmap(enum fixed_addresses idx,
 			 unsigned long phys, pgprot_t flags);
+extern void __clear_fixmap(enum fixed_addresses idx, pgprot_t flags);
 
 #define set_fixmap(idx, phys) \
 		__set_fixmap(idx, phys, PAGE_KERNEL)
diff --git a/arch/sh/include/asm/fpu.h b/arch/sh/include/asm/fpu.h
index fb6bbb9..06c4281 100644
--- a/arch/sh/include/asm/fpu.h
+++ b/arch/sh/include/asm/fpu.h
@@ -2,8 +2,8 @@
 #define __ASM_SH_FPU_H
 
 #ifndef __ASSEMBLY__
-#include <linux/preempt.h>
-#include <asm/ptrace.h>
+
+struct task_struct;
 
 #ifdef CONFIG_SH_FPU
 static inline void release_fpu(struct pt_regs *regs)
@@ -16,22 +16,23 @@
 	regs->sr &= ~SR_FD;
 }
 
-struct task_struct;
-
 extern void save_fpu(struct task_struct *__tsk);
-void fpu_state_restore(struct pt_regs *regs);
+extern void restore_fpu(struct task_struct *__tsk);
+extern void fpu_state_restore(struct pt_regs *regs);
+extern void __fpu_state_restore(void);
 #else
-
-#define save_fpu(tsk)		do { } while (0)
-#define release_fpu(regs)	do { } while (0)
-#define grab_fpu(regs)		do { } while (0)
-#define fpu_state_restore(regs)	do { } while (0)
-
+#define save_fpu(tsk)			do { } while (0)
+#define restore_fpu(tsk)		do { } while (0)
+#define release_fpu(regs)		do { } while (0)
+#define grab_fpu(regs)			do { } while (0)
+#define fpu_state_restore(regs)		do { } while (0)
+#define __fpu_state_restore(regs)	do { } while (0)
 #endif
 
 struct user_regset;
 
 extern int do_fpu_inst(unsigned short, struct pt_regs *);
+extern int init_fpu(struct task_struct *);
 
 extern int fpregs_get(struct task_struct *target,
 		      const struct user_regset *regset,
@@ -65,18 +66,6 @@
 	preempt_enable();
 }
 
-static inline int init_fpu(struct task_struct *tsk)
-{
-	if (tsk_used_math(tsk)) {
-		if ((boot_cpu_data.flags & CPU_HAS_FPU) && tsk == current)
-			unlazy_fpu(tsk, task_pt_regs(tsk));
-		return 0;
-	}
-
-	set_stopped_child_used_math(tsk);
-	return 0;
-}
-
 #endif /* __ASSEMBLY__ */
 
 #endif /* __ASM_SH_FPU_H */
diff --git a/arch/sh/include/asm/hw_breakpoint.h b/arch/sh/include/asm/hw_breakpoint.h
new file mode 100644
index 0000000..965dd78
--- /dev/null
+++ b/arch/sh/include/asm/hw_breakpoint.h
@@ -0,0 +1,67 @@
+#ifndef __ASM_SH_HW_BREAKPOINT_H
+#define __ASM_SH_HW_BREAKPOINT_H
+
+#ifdef __KERNEL__
+#define __ARCH_HW_BREAKPOINT_H
+
+#include <linux/kdebug.h>
+#include <linux/types.h>
+
+struct arch_hw_breakpoint {
+	char		*name; /* Contains name of the symbol to set bkpt */
+	unsigned long	address;
+	u16		len;
+	u16		type;
+};
+
+enum {
+	SH_BREAKPOINT_READ	= (1 << 1),
+	SH_BREAKPOINT_WRITE	= (1 << 2),
+	SH_BREAKPOINT_RW	= SH_BREAKPOINT_READ | SH_BREAKPOINT_WRITE,
+
+	SH_BREAKPOINT_LEN_1	= (1 << 12),
+	SH_BREAKPOINT_LEN_2	= (1 << 13),
+	SH_BREAKPOINT_LEN_4	= SH_BREAKPOINT_LEN_1 | SH_BREAKPOINT_LEN_2,
+	SH_BREAKPOINT_LEN_8	= (1 << 14),
+};
+
+struct sh_ubc {
+	const char	*name;
+	unsigned int	num_events;
+	unsigned int	trap_nr;
+	void		(*enable)(struct arch_hw_breakpoint *, int);
+	void		(*disable)(struct arch_hw_breakpoint *, int);
+	void		(*enable_all)(unsigned long);
+	void		(*disable_all)(void);
+	unsigned long	(*active_mask)(void);
+	unsigned long	(*triggered_mask)(void);
+	void		(*clear_triggered_mask)(unsigned long);
+	struct clk	*clk;	/* optional interface clock / MSTP bit */
+};
+
+struct perf_event;
+struct task_struct;
+struct pmu;
+
+/* Maximum number of UBC channels */
+#define HBP_NUM		2
+
+/* arch/sh/kernel/hw_breakpoint.c */
+extern int arch_check_va_in_userspace(unsigned long va, u16 hbp_len);
+extern int arch_validate_hwbkpt_settings(struct perf_event *bp,
+					 struct task_struct *tsk);
+extern int hw_breakpoint_exceptions_notify(struct notifier_block *unused,
+					   unsigned long val, void *data);
+
+int arch_install_hw_breakpoint(struct perf_event *bp);
+void arch_uninstall_hw_breakpoint(struct perf_event *bp);
+void hw_breakpoint_pmu_read(struct perf_event *bp);
+void hw_breakpoint_pmu_unthrottle(struct perf_event *bp);
+
+extern void arch_fill_perf_breakpoint(struct perf_event *bp);
+extern int register_sh_ubc(struct sh_ubc *);
+
+extern struct pmu perf_ops_bp;
+
+#endif /* __KERNEL__ */
+#endif /* __ASM_SH_HW_BREAKPOINT_H */
diff --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h
index 026dd65..7dab7b23 100644
--- a/arch/sh/include/asm/io.h
+++ b/arch/sh/include/asm/io.h
@@ -22,6 +22,7 @@
  * for old compat code for I/O offseting to SuperIOs, all of which are
  * better handled through the machvec ioport mapping routines these days.
  */
+#include <linux/errno.h>
 #include <asm/cache.h>
 #include <asm/system.h>
 #include <asm/addrspace.h>
@@ -79,16 +80,51 @@
 #define writel(v,a)		({ __raw_writel((v),(a)); mb(); })
 #define writeq(v,a)		({ __raw_writeq((v),(a)); mb(); })
 
-/* SuperH on-chip I/O functions */
-#define ctrl_inb		__raw_readb
-#define ctrl_inw		__raw_readw
-#define ctrl_inl		__raw_readl
-#define ctrl_inq		__raw_readq
+/*
+ * Legacy SuperH on-chip I/O functions
+ *
+ * These are all deprecated, all new (and especially cross-platform) code
+ * should be using the __raw_xxx() routines directly.
+ */
+static inline u8 __deprecated ctrl_inb(unsigned long addr)
+{
+	return __raw_readb(addr);
+}
 
-#define ctrl_outb		__raw_writeb
-#define ctrl_outw		__raw_writew
-#define ctrl_outl		__raw_writel
-#define ctrl_outq		__raw_writeq
+static inline u16 __deprecated ctrl_inw(unsigned long addr)
+{
+	return __raw_readw(addr);
+}
+
+static inline u32 __deprecated ctrl_inl(unsigned long addr)
+{
+	return __raw_readl(addr);
+}
+
+static inline u64 __deprecated ctrl_inq(unsigned long addr)
+{
+	return __raw_readq(addr);
+}
+
+static inline void __deprecated ctrl_outb(u8 v, unsigned long addr)
+{
+	__raw_writeb(v, addr);
+}
+
+static inline void __deprecated ctrl_outw(u16 v, unsigned long addr)
+{
+	__raw_writew(v, addr);
+}
+
+static inline void __deprecated ctrl_outl(u32 v, unsigned long addr)
+{
+	__raw_writel(v, addr);
+}
+
+static inline void __deprecated ctrl_outq(u64 v, unsigned long addr)
+{
+	__raw_writeq(v, addr);
+}
 
 extern unsigned long generic_io_base;
 
@@ -97,6 +133,28 @@
 	__raw_readw(generic_io_base);
 }
 
+#define __BUILD_UNCACHED_IO(bwlq, type)					\
+static inline type read##bwlq##_uncached(unsigned long addr)		\
+{									\
+	type ret;							\
+	jump_to_uncached();						\
+	ret = __raw_read##bwlq(addr);					\
+	back_to_cached();						\
+	return ret;							\
+}									\
+									\
+static inline void write##bwlq##_uncached(type v, unsigned long addr)	\
+{									\
+	jump_to_uncached();						\
+	__raw_write##bwlq(v, addr);					\
+	back_to_cached();						\
+}
+
+__BUILD_UNCACHED_IO(b, u8)
+__BUILD_UNCACHED_IO(w, u16)
+__BUILD_UNCACHED_IO(l, u32)
+__BUILD_UNCACHED_IO(q, u64)
+
 #define __BUILD_MEMORY_STRING(bwlq, type)				\
 									\
 static inline void __raw_writes##bwlq(volatile void __iomem *mem,	\
@@ -234,28 +292,21 @@
  */
 #ifdef CONFIG_MMU
 void __iomem *__ioremap_caller(unsigned long offset, unsigned long size,
-			       unsigned long flags, void *caller);
+			       pgprot_t prot, void *caller);
 void __iounmap(void __iomem *addr);
 
 static inline void __iomem *
-__ioremap(unsigned long offset, unsigned long size, unsigned long flags)
+__ioremap(unsigned long offset, unsigned long size, pgprot_t prot)
 {
-	return __ioremap_caller(offset, size, flags, __builtin_return_address(0));
+	return __ioremap_caller(offset, size, prot, __builtin_return_address(0));
 }
 
 static inline void __iomem *
-__ioremap_mode(unsigned long offset, unsigned long size, unsigned long flags)
+__ioremap_29bit(unsigned long offset, unsigned long size, pgprot_t prot)
 {
-#if defined(CONFIG_SUPERH32) && !defined(CONFIG_PMB_FIXED) && !defined(CONFIG_PMB)
+#ifdef CONFIG_29BIT
 	unsigned long last_addr = offset + size - 1;
-#endif
-	void __iomem *ret;
 
-	ret = __ioremap_trapped(offset, size);
-	if (ret)
-		return ret;
-
-#if defined(CONFIG_SUPERH32) && !defined(CONFIG_PMB_FIXED) && !defined(CONFIG_PMB)
 	/*
 	 * For P1 and P2 space this is trivial, as everything is already
 	 * mapped. Uncached access for P1 addresses are done through P2.
@@ -263,7 +314,7 @@
 	 * mapping must be done by the PMB or by using page tables.
 	 */
 	if (likely(PXSEG(offset) < P3SEG && PXSEG(last_addr) < P3SEG)) {
-		if (unlikely(flags & _PAGE_CACHABLE))
+		if (unlikely(pgprot_val(prot) & _PAGE_CACHABLE))
 			return (void __iomem *)P1SEGADDR(offset);
 
 		return (void __iomem *)P2SEGADDR(offset);
@@ -274,26 +325,70 @@
 		return (void __iomem *)P4SEGADDR(offset);
 #endif
 
-	return __ioremap(offset, size, flags);
+	return NULL;
+}
+
+static inline void __iomem *
+__ioremap_mode(unsigned long offset, unsigned long size, pgprot_t prot)
+{
+	void __iomem *ret;
+
+	ret = __ioremap_trapped(offset, size);
+	if (ret)
+		return ret;
+
+	ret = __ioremap_29bit(offset, size, prot);
+	if (ret)
+		return ret;
+
+	return __ioremap(offset, size, prot);
 }
 #else
-#define __ioremap(offset, size, flags)		((void __iomem *)(offset))
-#define __ioremap_mode(offset, size, flags)	((void __iomem *)(offset))
+#define __ioremap(offset, size, prot)		((void __iomem *)(offset))
+#define __ioremap_mode(offset, size, prot)	((void __iomem *)(offset))
 #define __iounmap(addr)				do { } while (0)
 #endif /* CONFIG_MMU */
 
-#define ioremap(offset, size)				\
-	__ioremap_mode((offset), (size), 0)
-#define ioremap_nocache(offset, size)			\
-	__ioremap_mode((offset), (size), 0)
-#define ioremap_cache(offset, size)			\
-	__ioremap_mode((offset), (size), _PAGE_CACHABLE)
-#define p3_ioremap(offset, size, flags)			\
-	__ioremap((offset), (size), (flags))
-#define ioremap_prot(offset, size, flags)		\
-	__ioremap_mode((offset), (size), (flags))
-#define iounmap(addr)					\
-	__iounmap((addr))
+static inline void __iomem *
+ioremap(unsigned long offset, unsigned long size)
+{
+	return __ioremap_mode(offset, size, PAGE_KERNEL_NOCACHE);
+}
+
+static inline void __iomem *
+ioremap_cache(unsigned long offset, unsigned long size)
+{
+	return __ioremap_mode(offset, size, PAGE_KERNEL);
+}
+
+#ifdef CONFIG_HAVE_IOREMAP_PROT
+static inline void __iomem *
+ioremap_prot(resource_size_t offset, unsigned long size, unsigned long flags)
+{
+	return __ioremap_mode(offset, size, __pgprot(flags));
+}
+#endif
+
+#ifdef CONFIG_IOREMAP_FIXED
+extern void __iomem *ioremap_fixed(resource_size_t, unsigned long,
+				   unsigned long, pgprot_t);
+extern int iounmap_fixed(void __iomem *);
+extern void ioremap_fixed_init(void);
+#else
+static inline void __iomem *
+ioremap_fixed(resource_size_t phys_addr, unsigned long offset,
+	      unsigned long size, pgprot_t prot)
+{
+	BUG();
+	return NULL;
+}
+
+static inline void ioremap_fixed_init(void) { }
+static inline int iounmap_fixed(void __iomem *addr) { return -EINVAL; }
+#endif
+
+#define ioremap_nocache	ioremap
+#define iounmap		__iounmap
 
 #define maybebadio(port) \
 	printk(KERN_ERR "bad PC-like io %s:%u for port 0x%lx at 0x%08x\n", \
diff --git a/arch/sh/include/asm/kdebug.h b/arch/sh/include/asm/kdebug.h
index 985219f..5f6d2e9 100644
--- a/arch/sh/include/asm/kdebug.h
+++ b/arch/sh/include/asm/kdebug.h
@@ -6,6 +6,8 @@
 	DIE_TRAP,
 	DIE_NMI,
 	DIE_OOPS,
+	DIE_BREAKPOINT,
+	DIE_SSTEP,
 };
 
 #endif /* __ASM_SH_KDEBUG_H */
diff --git a/arch/sh/include/asm/mmu.h b/arch/sh/include/asm/mmu.h
index c7426ad..15a05b6 100644
--- a/arch/sh/include/asm/mmu.h
+++ b/arch/sh/include/asm/mmu.h
@@ -11,7 +11,9 @@
 
 #define PMB_ADDR		0xf6100000
 #define PMB_DATA		0xf7100000
-#define PMB_ENTRY_MAX		16
+
+#define NR_PMB_ENTRIES		16
+
 #define PMB_E_MASK		0x0000000f
 #define PMB_E_SHIFT		8
 
@@ -25,11 +27,15 @@
 #define PMB_C			0x00000008
 #define PMB_WT			0x00000001
 #define PMB_UB			0x00000200
+#define PMB_CACHE_MASK		(PMB_C | PMB_WT | PMB_UB)
 #define PMB_V			0x00000100
 
 #define PMB_NO_ENTRY		(-1)
 
 #ifndef __ASSEMBLY__
+#include <linux/errno.h>
+#include <linux/threads.h>
+#include <asm/page.h>
 
 /* Default "unsigned long" context */
 typedef unsigned long mm_context_id_t[NR_CPUS];
@@ -47,29 +53,30 @@
 #endif
 } mm_context_t;
 
-struct pmb_entry;
-
-struct pmb_entry {
-	unsigned long vpn;
-	unsigned long ppn;
-	unsigned long flags;
-
-	/*
-	 * 0 .. NR_PMB_ENTRIES for specific entry selection, or
-	 * PMB_NO_ENTRY to search for a free one
-	 */
-	int entry;
-
-	struct pmb_entry *next;
-	/* Adjacent entry link for contiguous multi-entry mappings */
-	struct pmb_entry *link;
-};
-
+#ifdef CONFIG_PMB
 /* arch/sh/mm/pmb.c */
 long pmb_remap(unsigned long virt, unsigned long phys,
-	       unsigned long size, unsigned long flags);
+	       unsigned long size, pgprot_t prot);
 void pmb_unmap(unsigned long addr);
-int pmb_init(void);
+void pmb_init(void);
+bool __in_29bit_mode(void);
+#else
+static inline long pmb_remap(unsigned long virt, unsigned long phys,
+			     unsigned long size, pgprot_t prot)
+{
+	return -EINVAL;
+}
+
+#define pmb_unmap(addr)		do { } while (0)
+#define pmb_init(addr)		do { } while (0)
+
+#ifdef CONFIG_29BIT
+#define __in_29bit_mode()	(1)
+#else
+#define __in_29bit_mode()	(0)
+#endif
+
+#endif /* CONFIG_PMB */
 #endif /* __ASSEMBLY__ */
 
 #endif /* __MMU_H */
diff --git a/arch/sh/include/asm/mmu_context.h b/arch/sh/include/asm/mmu_context.h
index 41080b1..384c747 100644
--- a/arch/sh/include/asm/mmu_context.h
+++ b/arch/sh/include/asm/mmu_context.h
@@ -158,7 +158,7 @@
 	unsigned int cpu = smp_processor_id();
 
 	/* Enable MMU */
-	ctrl_outl(MMU_CONTROL_INIT, MMUCR);
+	__raw_writel(MMU_CONTROL_INIT, MMUCR);
 	ctrl_barrier();
 
 	if (asid_cache(cpu) == NO_CONTEXT)
@@ -171,9 +171,9 @@
 {
 	unsigned long cr;
 
-	cr = ctrl_inl(MMUCR);
+	cr = __raw_readl(MMUCR);
 	cr &= ~MMU_CONTROL_INIT;
-	ctrl_outl(cr, MMUCR);
+	__raw_writel(cr, MMUCR);
 
 	ctrl_barrier();
 }
diff --git a/arch/sh/include/asm/mmu_context_32.h b/arch/sh/include/asm/mmu_context_32.h
index 8ef800c..10e2e17 100644
--- a/arch/sh/include/asm/mmu_context_32.h
+++ b/arch/sh/include/asm/mmu_context_32.h
@@ -49,11 +49,11 @@
 /* MMU_TTB is used for optimizing the fault handling. */
 static inline void set_TTB(pgd_t *pgd)
 {
-	ctrl_outl((unsigned long)pgd, MMU_TTB);
+	__raw_writel((unsigned long)pgd, MMU_TTB);
 }
 
 static inline pgd_t *get_TTB(void)
 {
-	return (pgd_t *)ctrl_inl(MMU_TTB);
+	return (pgd_t *)__raw_readl(MMU_TTB);
 }
 #endif /* __ASM_SH_MMU_CONTEXT_32_H */
diff --git a/arch/sh/include/asm/module.h b/arch/sh/include/asm/module.h
index 068bf16..b7927de 100644
--- a/arch/sh/include/asm/module.h
+++ b/arch/sh/include/asm/module.h
@@ -1,7 +1,22 @@
 #ifndef _ASM_SH_MODULE_H
 #define _ASM_SH_MODULE_H
 
-#include <asm-generic/module.h>
+struct mod_arch_specific {
+#ifdef CONFIG_DWARF_UNWINDER
+	struct list_head fde_list;
+	struct list_head cie_list;
+#endif
+};
+
+#ifdef CONFIG_64BIT
+#define Elf_Shdr Elf64_Shdr
+#define Elf_Sym Elf64_Sym
+#define Elf_Ehdr Elf64_Ehdr
+#else
+#define Elf_Shdr Elf32_Shdr
+#define Elf_Sym Elf32_Sym
+#define Elf_Ehdr Elf32_Ehdr
+#endif
 
 #ifdef CONFIG_CPU_LITTLE_ENDIAN
 # ifdef CONFIG_CPU_SH2
diff --git a/arch/sh/include/asm/page.h b/arch/sh/include/asm/page.h
index 81bffc0..d71feb3 100644
--- a/arch/sh/include/asm/page.h
+++ b/arch/sh/include/asm/page.h
@@ -45,6 +45,7 @@
 #endif
 
 #ifndef __ASSEMBLY__
+#include <asm/uncached.h>
 
 extern unsigned long shm_align_mask;
 extern unsigned long max_low_pfn, min_low_pfn;
@@ -56,7 +57,6 @@
 	return (addr1 ^ addr2) & shm_align_mask;
 }
 
-
 #define clear_page(page)	memset((void *)(page), 0, PAGE_SIZE)
 extern void copy_page(void *to, void *from);
 
@@ -88,7 +88,7 @@
 #define __pte(x)	((pte_t) { (x) } )
 #else
 typedef struct { unsigned long long pte_low; } pte_t;
-typedef struct { unsigned long pgprot; } pgprot_t;
+typedef struct { unsigned long long pgprot; } pgprot_t;
 typedef struct { unsigned long pgd; } pgd_t;
 #define pte_val(x)	((x).pte_low)
 #define __pte(x)	((pte_t) { (x) } )
@@ -127,12 +127,7 @@
  * is not visible (it is part of the PMB mapping) and so needs to be
  * added or subtracted as required.
  */
-#if defined(CONFIG_PMB_FIXED)
-/* phys = virt - PAGE_OFFSET - (__MEMORY_START & 0xe0000000) */
-#define PMB_OFFSET	(PAGE_OFFSET - PXSEG(__MEMORY_START))
-#define __pa(x)	((unsigned long)(x) - PMB_OFFSET)
-#define __va(x)	((void *)((unsigned long)(x) + PMB_OFFSET))
-#elif defined(CONFIG_32BIT)
+#ifdef CONFIG_PMB
 #define __pa(x)	((unsigned long)(x)-PAGE_OFFSET+__MEMORY_START)
 #define __va(x)	((void *)((unsigned long)(x)+PAGE_OFFSET-__MEMORY_START))
 #else
@@ -140,6 +135,14 @@
 #define __va(x)	((void *)((unsigned long)(x)+PAGE_OFFSET))
 #endif
 
+#ifdef CONFIG_UNCACHED_MAPPING
+#define UNCAC_ADDR(addr)	((addr) - PAGE_OFFSET + uncached_start)
+#define CAC_ADDR(addr)		((addr) - uncached_start + PAGE_OFFSET)
+#else
+#define UNCAC_ADDR(addr)	((addr))
+#define CAC_ADDR(addr)		((addr))
+#endif
+
 #define pfn_to_kaddr(pfn)	__va((pfn) << PAGE_SHIFT)
 #define page_to_phys(page)	(page_to_pfn(page) << PAGE_SHIFT)
 
diff --git a/arch/sh/include/asm/pci.h b/arch/sh/include/asm/pci.h
index 67f3999..1042f7f 100644
--- a/arch/sh/include/asm/pci.h
+++ b/arch/sh/include/asm/pci.h
@@ -15,20 +15,49 @@
  */
 struct pci_channel {
 	struct pci_channel	*next;
+	struct pci_bus		*bus;
 
 	struct pci_ops		*pci_ops;
-	struct resource		*io_resource;
-	struct resource		*mem_resource;
+
+	struct resource		*resources;
+	unsigned int		nr_resources;
 
 	unsigned long		io_offset;
 	unsigned long		mem_offset;
 
 	unsigned long		reg_base;
-
 	unsigned long		io_map_base;
+
+	unsigned int		index;
+	unsigned int		need_domain_info;
+
+	/* Optional error handling */
+	struct timer_list	err_timer, serr_timer;
+	unsigned int		err_irq, serr_irq;
 };
 
-extern void register_pci_controller(struct pci_channel *hose);
+/* arch/sh/drivers/pci/pci.c */
+extern int register_pci_controller(struct pci_channel *hose);
+extern void pcibios_report_status(unsigned int status_mask, int warn);
+
+/* arch/sh/drivers/pci/common.c */
+extern int early_read_config_byte(struct pci_channel *hose, int top_bus,
+				  int bus, int devfn, int offset, u8 *value);
+extern int early_read_config_word(struct pci_channel *hose, int top_bus,
+				  int bus, int devfn, int offset, u16 *value);
+extern int early_read_config_dword(struct pci_channel *hose, int top_bus,
+				   int bus, int devfn, int offset, u32 *value);
+extern int early_write_config_byte(struct pci_channel *hose, int top_bus,
+				   int bus, int devfn, int offset, u8 value);
+extern int early_write_config_word(struct pci_channel *hose, int top_bus,
+				   int bus, int devfn, int offset, u16 value);
+extern int early_write_config_dword(struct pci_channel *hose, int top_bus,
+				    int bus, int devfn, int offset, u32 value);
+extern void pcibios_enable_timers(struct pci_channel *hose);
+extern unsigned int pcibios_handle_status_errors(unsigned long addr,
+				 unsigned int status, struct pci_channel *hose);
+extern int pci_is_66mhz_capable(struct pci_channel *hose,
+				int top_bus, int current_bus);
 
 extern unsigned long PCIBIOS_MIN_IO, PCIBIOS_MIN_MEM;
 
@@ -99,20 +128,6 @@
 }
 #endif
 
-#ifdef CONFIG_SUPERH32
-/*
- * If we're on an SH7751 or SH7780 PCI controller, PCI memory is mapped
- * at the end of the address space in a special non-translatable area.
- */
-#define PCI_MEM_FIXED_START	0xfd000000
-#define PCI_MEM_FIXED_END	(PCI_MEM_FIXED_START + 0x01000000)
-
-#define is_pci_memory_fixed_range(s, e)	\
-	((s) >= PCI_MEM_FIXED_START && (e) < PCI_MEM_FIXED_END)
-#else
-#define is_pci_memory_fixed_range(s, e)	(0)
-#endif
-
 /* Board-specific fixup routines. */
 int pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin);
 
@@ -122,6 +137,14 @@
 extern void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
 				    struct pci_bus_region *region);
 
+#define pci_domain_nr(bus) ((struct pci_channel *)(bus)->sysdata)->index
+
+static inline int pci_proc_domain(struct pci_bus *bus)
+{
+	struct pci_channel *hose = bus->sysdata;
+	return hose->need_domain_info;
+}
+
 /* Chances are this interrupt is wired PC-style ...  */
 static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
 {
diff --git a/arch/sh/include/asm/pgalloc.h b/arch/sh/include/asm/pgalloc.h
index 63ca37b..8c00785 100644
--- a/arch/sh/include/asm/pgalloc.h
+++ b/arch/sh/include/asm/pgalloc.h
@@ -4,8 +4,16 @@
 #include <linux/quicklist.h>
 #include <asm/page.h>
 
-#define QUICK_PGD 0	/* We preserve special mappings over free */
-#define QUICK_PT 1	/* Other page table pages that are zero on free */
+#define QUICK_PT 0	/* Other page table pages that are zero on free */
+
+extern pgd_t *pgd_alloc(struct mm_struct *);
+extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
+
+#if PAGETABLE_LEVELS > 2
+extern void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd);
+extern pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address);
+extern void pmd_free(struct mm_struct *mm, pmd_t *pmd);
+#endif
 
 static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd,
 				       pte_t *pte)
@@ -20,28 +28,9 @@
 }
 #define pmd_pgtable(pmd) pmd_page(pmd)
 
-static inline void pgd_ctor(void *x)
-{
-	pgd_t *pgd = x;
-
-	memcpy(pgd + USER_PTRS_PER_PGD,
-	       swapper_pg_dir + USER_PTRS_PER_PGD,
-	       (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
-}
-
 /*
  * Allocate and free page tables.
  */
-static inline pgd_t *pgd_alloc(struct mm_struct *mm)
-{
-	return quicklist_alloc(QUICK_PGD, GFP_KERNEL | __GFP_REPEAT, pgd_ctor);
-}
-
-static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
-{
-	quicklist_free(QUICK_PGD, NULL, pgd);
-}
-
 static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
 					  unsigned long address)
 {
@@ -81,7 +70,6 @@
 
 static inline void check_pgt_cache(void)
 {
-	quicklist_trim(QUICK_PGD, NULL, 25, 16);
 	quicklist_trim(QUICK_PT, NULL, 25, 16);
 }
 
diff --git a/arch/sh/include/asm/pgtable-2level.h b/arch/sh/include/asm/pgtable-2level.h
new file mode 100644
index 0000000..19bd89d
--- /dev/null
+++ b/arch/sh/include/asm/pgtable-2level.h
@@ -0,0 +1,23 @@
+#ifndef __ASM_SH_PGTABLE_2LEVEL_H
+#define __ASM_SH_PGTABLE_2LEVEL_H
+
+#include <asm-generic/pgtable-nopmd.h>
+
+/*
+ * traditional two-level paging structure
+ */
+#define PAGETABLE_LEVELS	2
+
+/* PTE bits */
+#define PTE_MAGNITUDE		2	/* 32-bit PTEs */
+
+#define PTE_SHIFT		PAGE_SHIFT
+#define PTE_BITS		(PTE_SHIFT - PTE_MAGNITUDE)
+
+/* PGD bits */
+#define PGDIR_SHIFT		(PTE_SHIFT + PTE_BITS)
+
+#define PTRS_PER_PGD		(PAGE_SIZE / (1 << PTE_MAGNITUDE))
+#define USER_PTRS_PER_PGD	(TASK_SIZE/PGDIR_SIZE)
+
+#endif /* __ASM_SH_PGTABLE_2LEVEL_H */
diff --git a/arch/sh/include/asm/pgtable-3level.h b/arch/sh/include/asm/pgtable-3level.h
new file mode 100644
index 0000000..249a985
--- /dev/null
+++ b/arch/sh/include/asm/pgtable-3level.h
@@ -0,0 +1,56 @@
+#ifndef __ASM_SH_PGTABLE_3LEVEL_H
+#define __ASM_SH_PGTABLE_3LEVEL_H
+
+#include <asm-generic/pgtable-nopud.h>
+
+/*
+ * Some cores need a 3-level page table layout, for example when using
+ * 64-bit PTEs and 4K pages.
+ */
+#define PAGETABLE_LEVELS	3
+
+#define PTE_MAGNITUDE		3	/* 64-bit PTEs on SH-X2 TLB */
+
+/* PGD bits */
+#define PGDIR_SHIFT		30
+
+#define PTRS_PER_PGD		4
+#define USER_PTRS_PER_PGD	2
+
+/* PMD bits */
+#define PMD_SHIFT	(PAGE_SHIFT + (PAGE_SHIFT - PTE_MAGNITUDE))
+#define PMD_SIZE	(1UL << PMD_SHIFT)
+#define PMD_MASK	(~(PMD_SIZE-1))
+
+#define PTRS_PER_PMD	((1 << PGDIR_SHIFT) / PMD_SIZE)
+
+#define pmd_ERROR(e) \
+	printk("%s:%d: bad pmd %016llx.\n", __FILE__, __LINE__, pmd_val(e))
+
+typedef struct { unsigned long long pmd; } pmd_t;
+#define pmd_val(x)	((x).pmd)
+#define __pmd(x)	((pmd_t) { (x) } )
+
+static inline unsigned long pud_page_vaddr(pud_t pud)
+{
+	return pud_val(pud);
+}
+
+#define pmd_index(address)	(((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
+static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address)
+{
+	return (pmd_t *)pud_page_vaddr(*pud) + pmd_index(address);
+}
+
+#define pud_none(x)	(!pud_val(x))
+#define pud_present(x)	(pud_val(x))
+#define pud_clear(xp)	do { set_pud(xp, __pud(0)); } while (0)
+#define	pud_bad(x)	(pud_val(x) & ~PAGE_MASK)
+
+/*
+ * (puds are folded into pgds so this doesn't get actually called,
+ * but the define is needed for a generic inline function.)
+ */
+#define set_pud(pudptr, pudval) do { *(pudptr) = (pudval); } while(0)
+
+#endif /* __ASM_SH_PGTABLE_3LEVEL_H */
diff --git a/arch/sh/include/asm/pgtable.h b/arch/sh/include/asm/pgtable.h
index ba3046e..aab7652 100644
--- a/arch/sh/include/asm/pgtable.h
+++ b/arch/sh/include/asm/pgtable.h
@@ -12,7 +12,11 @@
 #ifndef __ASM_SH_PGTABLE_H
 #define __ASM_SH_PGTABLE_H
 
-#include <asm-generic/pgtable-nopmd.h>
+#ifdef CONFIG_X2TLB
+#include <asm/pgtable-3level.h>
+#else
+#include <asm/pgtable-2level.h>
+#endif
 #include <asm/page.h>
 
 #ifndef __ASSEMBLY__
@@ -51,28 +55,12 @@
 #define	NPHYS_SIGN	(1LL << (NPHYS - 1))
 #define	NPHYS_MASK	(-1LL << NPHYS)
 
-/*
- * traditional two-level paging structure
- */
-/* PTE bits */
-#if defined(CONFIG_X2TLB) || defined(CONFIG_SUPERH64)
-# define PTE_MAGNITUDE	3	/* 64-bit PTEs on extended mode SH-X2 TLB */
-#else
-# define PTE_MAGNITUDE	2	/* 32-bit PTEs */
-#endif
-#define PTE_SHIFT	PAGE_SHIFT
-#define PTE_BITS	(PTE_SHIFT - PTE_MAGNITUDE)
-
-/* PGD bits */
-#define PGDIR_SHIFT	(PTE_SHIFT + PTE_BITS)
 #define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
 #define PGDIR_MASK	(~(PGDIR_SIZE-1))
 
 /* Entries per level */
 #define PTRS_PER_PTE	(PAGE_SIZE / (1 << PTE_MAGNITUDE))
-#define PTRS_PER_PGD	(PAGE_SIZE / sizeof(pgd_t))
 
-#define USER_PTRS_PER_PGD	(TASK_SIZE/PGDIR_SIZE)
 #define FIRST_USER_ADDRESS	0
 
 #define PHYS_ADDR_MASK29		0x1fffffff
@@ -153,9 +141,9 @@
 #define pte_pfn(x)		((unsigned long)(((x).pte_low >> PAGE_SHIFT)))
 
 /*
- * No page table caches to initialise
+ * Initialise the page table caches
  */
-#define pgtable_cache_init()	do { } while (0)
+extern void pgtable_cache_init(void);
 
 struct vm_area_struct;
 
diff --git a/arch/sh/include/asm/pgtable_32.h b/arch/sh/include/asm/pgtable_32.h
index 5003ee8..e172d69 100644
--- a/arch/sh/include/asm/pgtable_32.h
+++ b/arch/sh/include/asm/pgtable_32.h
@@ -71,6 +71,8 @@
 #define _PAGE_EXT_KERN_WRITE	0x1000	/* EPR4-bit: Kernel space writable */
 #define _PAGE_EXT_KERN_READ	0x2000	/* EPR5-bit: Kernel space readable */
 
+#define _PAGE_EXT_WIRED		0x4000	/* software: Wire TLB entry */
+
 /* Wrapper for extended mode pgprot twiddling */
 #define _PAGE_EXT(x)		((unsigned long long)(x) << 32)
 
@@ -141,12 +143,14 @@
 # elif defined(CONFIG_HUGETLB_PAGE_SIZE_64MB)
 #  define _PAGE_SZHUGE	(_PAGE_EXT_ESZ2 | _PAGE_EXT_ESZ3)
 # endif
+# define _PAGE_WIRED	(_PAGE_EXT(_PAGE_EXT_WIRED))
 #else
 # if defined(CONFIG_HUGETLB_PAGE_SIZE_64K)
 #  define _PAGE_SZHUGE	(_PAGE_SZ1)
 # elif defined(CONFIG_HUGETLB_PAGE_SIZE_1MB)
 #  define _PAGE_SZHUGE	(_PAGE_SZ0 | _PAGE_SZ1)
 # endif
+# define _PAGE_WIRED	(0)
 #endif
 
 /*
diff --git a/arch/sh/include/asm/pgtable_64.h b/arch/sh/include/asm/pgtable_64.h
index 17cdbec..0ee4677 100644
--- a/arch/sh/include/asm/pgtable_64.h
+++ b/arch/sh/include/asm/pgtable_64.h
@@ -43,11 +43,6 @@
 }
 #define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
 
-static __inline__ void pmd_set(pmd_t *pmdp,pte_t *ptep)
-{
-	pmd_val(*pmdp) = (unsigned long) ptep;
-}
-
 /*
  * PGD defines. Top level.
  */
@@ -128,8 +123,21 @@
 #define _PAGE_DIRTY	0x400  /* software: page accessed in write */
 #define _PAGE_ACCESSED	0x800  /* software: page referenced */
 
+/* Wrapper for extended mode pgprot twiddling */
+#define _PAGE_EXT(x)		((unsigned long long)(x) << 32)
+
+/*
+ * We can use the sign-extended bits in the PTEL to get 32 bits of
+ * software flags. This works for now because no implementations uses
+ * anything above the PPN field.
+ */
+#define _PAGE_WIRED	_PAGE_EXT(0x001) /* software: wire the tlb entry */
+
+#define _PAGE_CLEAR_FLAGS	(_PAGE_PRESENT | _PAGE_FILE | _PAGE_SHARED | \
+				 _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_WIRED)
+
 /* Mask which drops software flags */
-#define _PAGE_FLAGS_HARDWARE_MASK	0xfffffffffffff3dbLL
+#define _PAGE_FLAGS_HARDWARE_MASK	(NEFF_MASK & ~(_PAGE_CLEAR_FLAGS))
 
 /*
  * HugeTLB support
@@ -203,12 +211,6 @@
 #define pgprot_writecombine(prot) __pgprot(pgprot_val(prot) & ~_PAGE_CACHABLE)
 
 /*
- * Handling allocation failures during page table setup.
- */
-extern void __handle_bad_pmd_kernel(pmd_t * pmd);
-#define __handle_bad_pmd(x)	__handle_bad_pmd_kernel(x)
-
-/*
  * PTE level access routines.
  *
  * Note1:
diff --git a/arch/sh/include/asm/processor.h b/arch/sh/include/asm/processor.h
index 017e0c1..9605e062 100644
--- a/arch/sh/include/asm/processor.h
+++ b/arch/sh/include/asm/processor.h
@@ -98,13 +98,34 @@
 
 /* Forward decl */
 struct seq_operations;
+struct task_struct;
 
 extern struct pt_regs fake_swapper_regs;
 
+/* arch/sh/kernel/process.c */
+extern unsigned int xstate_size;
+extern void free_thread_xstate(struct task_struct *);
+extern struct kmem_cache *task_xstate_cachep;
+
+/* arch/sh/mm/alignment.c */
+extern int get_unalign_ctl(struct task_struct *, unsigned long addr);
+extern int set_unalign_ctl(struct task_struct *, unsigned int val);
+
+#define GET_UNALIGN_CTL(tsk, addr)	get_unalign_ctl((tsk), (addr))
+#define SET_UNALIGN_CTL(tsk, val)	set_unalign_ctl((tsk), (val))
+
+/* arch/sh/mm/init.c */
+extern unsigned int mem_init_done;
+
 /* arch/sh/kernel/setup.c */
 const char *get_cpu_subtype(struct sh_cpuinfo *c);
 extern const struct seq_operations cpuinfo_op;
 
+/* thread_struct flags */
+#define SH_THREAD_UAC_NOPRINT	(1 << 0)
+#define SH_THREAD_UAC_SIGBUS	(1 << 1)
+#define SH_THREAD_UAC_MASK	(SH_THREAD_UAC_NOPRINT | SH_THREAD_UAC_SIGBUS)
+
 /* processor boot mode configuration */
 #define MODE_PIN0 (1 << 0)
 #define MODE_PIN1 (1 << 1)
diff --git a/arch/sh/include/asm/processor_32.h b/arch/sh/include/asm/processor_32.h
index 1f3d6fa..572b4eb 100644
--- a/arch/sh/include/asm/processor_32.h
+++ b/arch/sh/include/asm/processor_32.h
@@ -14,6 +14,7 @@
 #include <asm/page.h>
 #include <asm/types.h>
 #include <asm/ptrace.h>
+#include <asm/hw_breakpoint.h>
 
 /*
  * Default implementation of macro that returns current
@@ -90,9 +91,9 @@
 	unsigned long entry_pc;
 };
 
-union sh_fpu_union {
-	struct sh_fpu_hard_struct hard;
-	struct sh_fpu_soft_struct soft;
+union thread_xstate {
+	struct sh_fpu_hard_struct hardfpu;
+	struct sh_fpu_soft_struct softfpu;
 };
 
 struct thread_struct {
@@ -100,38 +101,30 @@
 	unsigned long sp;
 	unsigned long pc;
 
-	/* Hardware debugging registers */
-	unsigned long ubc_pc;
+	/* Various thread flags, see SH_THREAD_xxx */
+	unsigned long flags;
 
-	/* floating point info */
-	union sh_fpu_union fpu;
+	/* Save middle states of ptrace breakpoints */
+	struct perf_event *ptrace_bps[HBP_NUM];
 
 #ifdef CONFIG_SH_DSP
 	/* Dsp status information */
 	struct sh_dsp_struct dsp_status;
 #endif
-};
 
-/* Count of active tasks with UBC settings */
-extern int ubc_usercnt;
+	/* Extended processor state */
+	union thread_xstate *xstate;
+};
 
 #define INIT_THREAD  {						\
 	.sp = sizeof(init_stack) + (long) &init_stack,		\
+	.flags = 0,						\
 }
 
-/*
- * Do necessary setup to start up a newly executed thread.
- */
-#define start_thread(_regs, new_pc, new_sp)	 \
-	set_fs(USER_DS);			 \
-	_regs->pr = 0;				 \
-	_regs->sr = SR_FD;	/* User mode. */ \
-	_regs->pc = new_pc;			 \
-	_regs->regs[15] = new_sp
-
 /* Forward declaration, a strange C thing */
 struct task_struct;
-struct mm_struct;
+
+extern void start_thread(struct pt_regs *regs, unsigned long new_pc, unsigned long new_sp);
 
 /* Free all resources held by a thread. */
 extern void release_thread(struct task_struct *);
diff --git a/arch/sh/include/asm/processor_64.h b/arch/sh/include/asm/processor_64.h
index 5727d31..621bc46 100644
--- a/arch/sh/include/asm/processor_64.h
+++ b/arch/sh/include/asm/processor_64.h
@@ -87,26 +87,31 @@
 	/* long status; * software status information */
 };
 
-#if 0
 /* Dummy fpu emulator  */
 struct sh_fpu_soft_struct {
-	unsigned long long fp_regs[32];
+	unsigned long fp_regs[64];
 	unsigned int fpscr;
 	unsigned char lookahead;
 	unsigned long entry_pc;
 };
-#endif
 
-union sh_fpu_union {
-	struct sh_fpu_hard_struct hard;
-	/* 'hard' itself only produces 32 bit alignment, yet we need
-	   to access it using 64 bit load/store as well. */
+union thread_xstate {
+	struct sh_fpu_hard_struct hardfpu;
+	struct sh_fpu_soft_struct softfpu;
+	/*
+	 * The structure definitions only produce 32 bit alignment, yet we need
+	 * to access them using 64 bit load/store as well.
+	 */
 	unsigned long long alignment_dummy;
 };
 
 struct thread_struct {
 	unsigned long sp;
 	unsigned long pc;
+
+	/* Various thread flags, see SH_THREAD_xxx */
+	unsigned long flags;
+
 	/* This stores the address of the pt_regs built during a context
 	   switch, or of the register save area built for a kernel mode
 	   exception.  It is used for backtracing the stack of a sleeping task
@@ -122,7 +127,7 @@
 	/* Hardware debugging registers may come here */
 
 	/* floating point info */
-	union sh_fpu_union fpu;
+	union thread_xstate *xstate;
 };
 
 #define INIT_MMAP \
@@ -137,7 +142,7 @@
 	.trap_no	= 0,			\
 	.error_code	= 0,			\
 	.address	= 0,			\
-	.fpu		= { { { 0, } }, }	\
+	.flags		= 0,			\
 }
 
 /*
diff --git a/arch/sh/include/asm/ptrace.h b/arch/sh/include/asm/ptrace.h
index 1dc12cb..e11b14e 100644
--- a/arch/sh/include/asm/ptrace.h
+++ b/arch/sh/include/asm/ptrace.h
@@ -102,13 +102,15 @@
 #define	PTRACE_GETDSPREGS	55	/* DSP registers */
 #define	PTRACE_SETDSPREGS	56
 
-#define PT_TEXT_END_ADDR 	240
-#define PT_TEXT_ADDR 		244	/* &(struct user)->start_code */
-#define PT_DATA_ADDR 		248	/* &(struct user)->start_data */
+#define PT_TEXT_END_ADDR	240
+#define PT_TEXT_ADDR		244	/* &(struct user)->start_code */
+#define PT_DATA_ADDR		248	/* &(struct user)->start_data */
 #define PT_TEXT_LEN		252
 
 #ifdef __KERNEL__
 #include <asm/addrspace.h>
+#include <asm/page.h>
+#include <asm/system.h>
 
 #define user_mode(regs)			(((regs)->sr & 0x40000000)==0)
 #define instruction_pointer(regs)	((unsigned long)(regs)->pc)
@@ -124,6 +126,12 @@
 extern void user_enable_single_step(struct task_struct *);
 extern void user_disable_single_step(struct task_struct *);
 
+struct perf_event;
+struct perf_sample_data;
+
+extern void ptrace_triggered(struct perf_event *bp, int nmi,
+		      struct perf_sample_data *data, struct pt_regs *regs);
+
 #define task_pt_regs(task) \
 	((struct pt_regs *) (task_stack_page(task) + THREAD_SIZE) - 1)
 
@@ -131,10 +139,8 @@
 {
 	unsigned long pc = instruction_pointer(regs);
 
-#ifdef P2SEG
-	if (pc >= P2SEG && pc < P3SEG)
-		pc -= 0x20000000;
-#endif
+	if (virt_addr_uncached(pc))
+		return CAC_ADDR(pc);
 
 	return pc;
 }
diff --git a/arch/sh/include/asm/reboot.h b/arch/sh/include/asm/reboot.h
new file mode 100644
index 0000000..b3da0c6
--- /dev/null
+++ b/arch/sh/include/asm/reboot.h
@@ -0,0 +1,21 @@
+#ifndef __ASM_SH_REBOOT_H
+#define __ASM_SH_REBOOT_H
+
+#include <linux/kdebug.h>
+
+struct pt_regs;
+
+struct machine_ops {
+	void (*restart)(char *cmd);
+	void (*halt)(void);
+	void (*power_off)(void);
+	void (*shutdown)(void);
+	void (*crash_shutdown)(struct pt_regs *);
+};
+
+extern struct machine_ops machine_ops;
+
+/* arch/sh/kernel/machine_kexec.c */
+void native_machine_crash_shutdown(struct pt_regs *regs);
+
+#endif /* __ASM_SH_REBOOT_H */
diff --git a/arch/sh/include/asm/setup.h b/arch/sh/include/asm/setup.h
index ce37435..4758325 100644
--- a/arch/sh/include/asm/setup.h
+++ b/arch/sh/include/asm/setup.h
@@ -18,7 +18,6 @@
 /* ... */
 #define COMMAND_LINE ((char *) (PARAM+0x100))
 
-int setup_early_printk(char *);
 void sh_mv_setup(void);
 
 #endif /* __KERNEL__ */
diff --git a/arch/sh/include/asm/sh_bios.h b/arch/sh/include/asm/sh_bios.h
index d9c96d7..95714c2 100644
--- a/arch/sh/include/asm/sh_bios.h
+++ b/arch/sh/include/asm/sh_bios.h
@@ -1,18 +1,27 @@
 #ifndef __ASM_SH_BIOS_H
 #define __ASM_SH_BIOS_H
 
+#ifdef CONFIG_SH_STANDARD_BIOS
+
 /*
  * Copyright (C) 2000 Greg Banks, Mitch Davis
  * C API to interface to the standard LinuxSH BIOS
  * usually from within the early stages of kernel boot.
  */
-
-
 extern void sh_bios_console_write(const char *buf, unsigned int len);
-extern void sh_bios_char_out(char ch);
 extern void sh_bios_gdb_detach(void);
 
 extern void sh_bios_get_node_addr(unsigned char *node_addr);
 extern void sh_bios_shutdown(unsigned int how);
 
+extern void sh_bios_vbr_init(void);
+extern void sh_bios_vbr_reload(void);
+
+#else
+
+static inline void sh_bios_vbr_init(void) { }
+static inline void sh_bios_vbr_reload(void) { }
+
+#endif /* CONFIG_SH_STANDARD_BIOS */
+
 #endif /* __ASM_SH_BIOS_H */
diff --git a/arch/sh/include/asm/suspend.h b/arch/sh/include/asm/suspend.h
index fe9c2a1..64eb41a 100644
--- a/arch/sh/include/asm/suspend.h
+++ b/arch/sh/include/asm/suspend.h
@@ -92,5 +92,6 @@
 #define SUSP_SH_USTANDBY	(1 << 3) /* SH-Mobile U-standby mode */
 #define SUSP_SH_SF		(1 << 4) /* Enable self-refresh */
 #define SUSP_SH_MMU		(1 << 5) /* Save/restore MMU and cache */
+#define SUSP_SH_REGS		(1 << 6) /* Save/restore registers */
 
 #endif /* _ASM_SH_SUSPEND_H */
diff --git a/arch/sh/include/asm/system.h b/arch/sh/include/asm/system.h
index c15415b..0bd7a17 100644
--- a/arch/sh/include/asm/system.h
+++ b/arch/sh/include/asm/system.h
@@ -10,7 +10,6 @@
 #include <linux/compiler.h>
 #include <linux/linkage.h>
 #include <asm/types.h>
-#include <asm/ptrace.h>
 
 #define AT_VECTOR_SIZE_ARCH 5 /* entries in ARCH_DLINFO */
 
@@ -32,7 +31,7 @@
 #define mb()		__asm__ __volatile__ ("synco": : :"memory")
 #define rmb()		mb()
 #define wmb()		__asm__ __volatile__ ("synco": : :"memory")
-#define ctrl_barrier()	__icbi(0xa8000000)
+#define ctrl_barrier()	__icbi(PAGE_OFFSET)
 #define read_barrier_depends()	do { } while(0)
 #else
 #define mb()		__asm__ __volatile__ ("": : :"memory")
@@ -114,6 +113,8 @@
 				    (unsigned long)_n_, sizeof(*(ptr))); \
   })
 
+struct pt_regs;
+
 extern void die(const char *str, struct pt_regs *regs, long err) __attribute__ ((noreturn));
 void free_initmem(void);
 void free_initrd_mem(unsigned long start, unsigned long end);
@@ -137,14 +138,14 @@
 #endif
 
 extern unsigned long cached_to_uncached;
+extern unsigned long uncached_size;
 
 extern struct dentry *sh_debugfs_root;
 
 void per_cpu_trap_init(void);
 void default_idle(void);
 void cpu_idle_wait(void);
-
-asmlinkage void break_point_trap(void);
+void stop_this_cpu(void *);
 
 #ifdef CONFIG_SUPERH32
 #define BUILD_TRAP_HANDLER(name)					\
diff --git a/arch/sh/include/asm/system_32.h b/arch/sh/include/asm/system_32.h
index 06814f5..51296b3 100644
--- a/arch/sh/include/asm/system_32.h
+++ b/arch/sh/include/asm/system_32.h
@@ -2,6 +2,7 @@
 #define __ASM_SH_SYSTEM_32_H
 
 #include <linux/types.h>
+#include <asm/mmu.h>
 
 #ifdef CONFIG_SH_DSP
 
@@ -144,9 +145,6 @@
 		__restore_dsp(prev);				\
 } while (0)
 
-#define __uses_jump_to_uncached \
-	noinline __attribute__ ((__section__ (".uncached.text")))
-
 /*
  * Jump to uncached area.
  * When handling TLB or caches, we need to do it from an uncached area.
@@ -216,6 +214,17 @@
 int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs,
 			    struct mem_access *ma, int);
 
+static inline void trigger_address_error(void)
+{
+	if (__in_29bit_mode())
+		__asm__ __volatile__ (
+			"ldc %0, sr\n\t"
+			"mov.l @%1, %0"
+			:
+			: "r" (0x10000000), "r" (0x80000001)
+		);
+}
+
 asmlinkage void do_address_error(struct pt_regs *regs,
 				 unsigned long writeaccess,
 				 unsigned long address);
diff --git a/arch/sh/include/asm/system_64.h b/arch/sh/include/asm/system_64.h
index ab1dd91..3633864 100644
--- a/arch/sh/include/asm/system_64.h
+++ b/arch/sh/include/asm/system_64.h
@@ -18,6 +18,7 @@
 /*
  *	switch_to() should switch tasks to task nr n, first
  */
+struct thread_struct;
 struct task_struct *sh64_switch_to(struct task_struct *prev,
 				   struct thread_struct *prev_thread,
 				   struct task_struct *next,
@@ -33,8 +34,6 @@
 			      &next->thread);			\
 } while (0)
 
-#define __uses_jump_to_uncached
-
 #define jump_to_uncached()	do { } while (0)
 #define back_to_cached()	do { } while (0)
 
@@ -48,6 +47,13 @@
 	return (unsigned long long)(signed long long)(signed long)val;
 }
 
+extern void phys_stext(void);
+
+static inline void trigger_address_error(void)
+{
+	phys_stext();
+}
+
 #define SR_BL_LL	0x0000000010000000LL
 
 static inline void set_bl_bit(void)
diff --git a/arch/sh/include/asm/thread_info.h b/arch/sh/include/asm/thread_info.h
index 1f3d927..55a36fe 100644
--- a/arch/sh/include/asm/thread_info.h
+++ b/arch/sh/include/asm/thread_info.h
@@ -93,14 +93,16 @@
 
 #define THREAD_SIZE_ORDER	(THREAD_SHIFT - PAGE_SHIFT)
 
-#else /* THREAD_SHIFT < PAGE_SHIFT */
-
-#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
+#endif
 
 extern struct thread_info *alloc_thread_info(struct task_struct *tsk);
 extern void free_thread_info(struct thread_info *ti);
+extern void arch_task_cache_init(void);
+#define arch_task_cache_init arch_task_cache_init
+extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src);
+extern void init_thread_xstate(void);
 
-#endif /* THREAD_SHIFT < PAGE_SHIFT */
+#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
 
 #endif /* __ASSEMBLY__ */
 
diff --git a/arch/sh/include/asm/tlb.h b/arch/sh/include/asm/tlb.h
index da8fe7a..75abb38 100644
--- a/arch/sh/include/asm/tlb.h
+++ b/arch/sh/include/asm/tlb.h
@@ -11,6 +11,7 @@
 #ifdef CONFIG_MMU
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
+#include <asm/mmu_context.h>
 
 /*
  * TLB handling.  This allows us to remove pages from the page
@@ -97,6 +98,22 @@
 
 #define tlb_migrate_finish(mm)		do { } while (0)
 
+#if defined(CONFIG_CPU_SH4) || defined(CONFIG_SUPERH64)
+extern void tlb_wire_entry(struct vm_area_struct *, unsigned long, pte_t);
+extern void tlb_unwire_entry(void);
+#else
+static inline void tlb_wire_entry(struct vm_area_struct *vma ,
+				  unsigned long addr, pte_t pte)
+{
+	BUG();
+}
+
+static inline void tlb_unwire_entry(void)
+{
+	BUG();
+}
+#endif
+
 #else /* CONFIG_MMU */
 
 #define tlb_start_vma(tlb, vma)				do { } while (0)
diff --git a/arch/sh/include/asm/ubc.h b/arch/sh/include/asm/ubc.h
deleted file mode 100644
index 9bf9616..0000000
--- a/arch/sh/include/asm/ubc.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * include/asm-sh/ubc.h
- *
- * Copyright (C) 1999 Niibe Yutaka
- * Copyright (C) 2002, 2003 Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-#ifndef __ASM_SH_UBC_H
-#define __ASM_SH_UBC_H
-#ifdef __KERNEL__
-
-#include <cpu/ubc.h>
-
-/* User Break Controller */
-#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709)
-#define UBC_TYPE_SH7729	(current_cpu_data.type == CPU_SH7729)
-#else
-#define UBC_TYPE_SH7729	0
-#endif
-
-#define BAMR_ASID		(1 << 2)
-#define BAMR_NONE		0
-#define BAMR_10			0x1
-#define BAMR_12			0x2
-#define BAMR_ALL		0x3
-#define BAMR_16			0x8
-#define BAMR_20			0x9
-
-#define BBR_INST		(1 << 4)
-#define BBR_DATA		(2 << 4)
-#define BBR_READ		(1 << 2)
-#define BBR_WRITE		(2 << 2)
-#define BBR_BYTE		0x1
-#define BBR_HALF		0x2
-#define BBR_LONG		0x3
-#define BBR_QUAD		(1 << 6)	/* SH7750 */
-#define BBR_CPU			(1 << 6)	/* SH7709A,SH7729 */
-#define BBR_DMA			(2 << 6)	/* SH7709A,SH7729 */
-
-#define BRCR_CMFA		(1 << 15)
-#define BRCR_CMFB		(1 << 14)
-
-#if defined CONFIG_CPU_SH2A
-#define BRCR_CMFCA		(1 << 15)
-#define BRCR_CMFCB		(1 << 14)
-#define BRCR_CMFDA		(1 << 13)
-#define BRCR_CMFDB		(1 << 12)
-#define BRCR_PCBB		(1 << 6)	/* 1: after execution */
-#define BRCR_PCBA		(1 << 5)	/* 1: after execution */
-#define BRCR_PCTE		0
-#else
-#define BRCR_PCTE		(1 << 11)
-#define BRCR_PCBA		(1 << 10)	/* 1: after execution */
-#define BRCR_DBEB		(1 << 7)
-#define BRCR_PCBB		(1 << 6)
-#define BRCR_SEQ		(1 << 3)
-#define BRCR_UBDE		(1 << 0)
-#endif
-
-#endif /* __KERNEL__ */
-#endif /* __ASM_SH_UBC_H */
diff --git a/arch/sh/include/asm/uncached.h b/arch/sh/include/asm/uncached.h
new file mode 100644
index 0000000..e3419f9
--- /dev/null
+++ b/arch/sh/include/asm/uncached.h
@@ -0,0 +1,18 @@
+#ifndef __ASM_SH_UNCACHED_H
+#define __ASM_SH_UNCACHED_H
+
+#include <linux/bug.h>
+
+#ifdef CONFIG_UNCACHED_MAPPING
+extern unsigned long uncached_start, uncached_end;
+
+extern int virt_addr_uncached(unsigned long kaddr);
+extern void uncached_init(void);
+extern void uncached_resize(unsigned long size);
+#else
+#define virt_addr_uncached(kaddr)	(0)
+#define uncached_init()			do { } while (0)
+#define uncached_resize(size)		BUG()
+#endif
+
+#endif /* __ASM_SH_UNCACHED_H */
diff --git a/arch/sh/include/asm/vmlinux.lds.h b/arch/sh/include/asm/vmlinux.lds.h
index 244ec4a..d58ad49 100644
--- a/arch/sh/include/asm/vmlinux.lds.h
+++ b/arch/sh/include/asm/vmlinux.lds.h
@@ -14,4 +14,12 @@
 #define DWARF_EH_FRAME
 #endif
 
+#ifdef CONFIG_SUPERH64
+#define EXTRA_TEXT		\
+	*(.text64)		\
+	*(.text..SHmedia32)
+#else
+#define EXTRA_TEXT
+#endif
+
 #endif /* __ASM_SH_VMLINUX_LDS_H */
diff --git a/arch/sh/include/asm/watchdog.h b/arch/sh/include/asm/watchdog.h
index 19dfff5..85a7aca 100644
--- a/arch/sh/include/asm/watchdog.h
+++ b/arch/sh/include/asm/watchdog.h
@@ -70,7 +70,7 @@
  */
 static inline __u32 sh_wdt_read_cnt(void)
 {
-	return ctrl_inl(WTCNT_R);
+	return __raw_readl(WTCNT_R);
 }
 
 /**
@@ -82,7 +82,7 @@
  */
 static inline void sh_wdt_write_cnt(__u32 val)
 {
-	ctrl_outl((WTCNT_HIGH << 24) | (__u32)val, WTCNT);
+	__raw_writel((WTCNT_HIGH << 24) | (__u32)val, WTCNT);
 }
 
 /**
@@ -94,7 +94,7 @@
  */
 static inline void sh_wdt_write_bst(__u32 val)
 {
-	ctrl_outl((WTBST_HIGH << 24) | (__u32)val, WTBST);
+	__raw_writel((WTBST_HIGH << 24) | (__u32)val, WTBST);
 }
 /**
  * 	sh_wdt_read_csr - Read from Control/Status Register
@@ -103,7 +103,7 @@
  */
 static inline __u32 sh_wdt_read_csr(void)
 {
-	return ctrl_inl(WTCSR_R);
+	return __raw_readl(WTCSR_R);
 }
 
 /**
@@ -115,7 +115,7 @@
  */
 static inline void sh_wdt_write_csr(__u32 val)
 {
-	ctrl_outl((WTCSR_HIGH << 24) | (__u32)val, WTCSR);
+	__raw_writel((WTCSR_HIGH << 24) | (__u32)val, WTCSR);
 }
 #else
 /**
@@ -124,7 +124,7 @@
  */
 static inline __u8 sh_wdt_read_cnt(void)
 {
-	return ctrl_inb(WTCNT_R);
+	return __raw_readb(WTCNT_R);
 }
 
 /**
@@ -136,7 +136,7 @@
  */
 static inline void sh_wdt_write_cnt(__u8 val)
 {
-	ctrl_outw((WTCNT_HIGH << 8) | (__u16)val, WTCNT);
+	__raw_writew((WTCNT_HIGH << 8) | (__u16)val, WTCNT);
 }
 
 /**
@@ -146,7 +146,7 @@
  */
 static inline __u8 sh_wdt_read_csr(void)
 {
-	return ctrl_inb(WTCSR_R);
+	return __raw_readb(WTCSR_R);
 }
 
 /**
@@ -158,7 +158,7 @@
  */
 static inline void sh_wdt_write_csr(__u8 val)
 {
-	ctrl_outw((WTCSR_HIGH << 8) | (__u16)val, WTCSR);
+	__raw_writew((WTCSR_HIGH << 8) | (__u16)val, WTCSR);
 }
 #endif /* CONFIG_CPU_SUBTYPE_SH7785 || CONFIG_CPU_SUBTYPE_SH7780 */
 #endif /* __KERNEL__ */
diff --git a/arch/sh/include/cpu-sh2/cpu/ubc.h b/arch/sh/include/cpu-sh2/cpu/ubc.h
deleted file mode 100644
index ba0e87f..0000000
--- a/arch/sh/include/cpu-sh2/cpu/ubc.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * include/asm-sh/cpu-sh2/ubc.h
- *
- * Copyright (C) 2003 Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-#ifndef __ASM_CPU_SH2_UBC_H
-#define __ASM_CPU_SH2_UBC_H
-
-#define UBC_BARA                0xffffff40
-#define UBC_BAMRA               0xffffff44
-#define UBC_BBRA                0xffffff48
-#define UBC_BARB                0xffffff60
-#define UBC_BAMRB               0xffffff64
-#define UBC_BBRB                0xffffff68
-#define UBC_BDRB                0xffffff70
-#define UBC_BDMRB               0xffffff74
-#define UBC_BRCR                0xffffff78
-
-/*
- * We don't have any ASID changes to make in the UBC on the SH-2.
- *
- * Make these purposely invalid to track misuse.
- */
-#define UBC_BASRA		0x00000000
-#define UBC_BASRB		0x00000000
-
-#endif /* __ASM_CPU_SH2_UBC_H */
-
diff --git a/arch/sh/include/cpu-sh2/cpu/watchdog.h b/arch/sh/include/cpu-sh2/cpu/watchdog.h
index 393161c..1eab8aa 100644
--- a/arch/sh/include/cpu-sh2/cpu/watchdog.h
+++ b/arch/sh/include/cpu-sh2/cpu/watchdog.h
@@ -44,7 +44,7 @@
 	/*
 	 * Same read/write brain-damage as for WTCNT here..
 	 */
-	return ctrl_inb(RSTCSR_R);
+	return __raw_readb(RSTCSR_R);
 }
 
 /**
@@ -62,7 +62,7 @@
 	 * we can't presently touch the WOVF bit, since the upper byte
 	 * has to be swapped for this. So just leave it alone..
 	 */
-	ctrl_outw((WTCNT_HIGH << 8) | (__u16)val, RSTCSR);
+	__raw_writeb((WTCNT_HIGH << 8) | (__u16)val, RSTCSR);
 }
 
 #endif /* __ASM_CPU_SH2_WATCHDOG_H */
diff --git a/arch/sh/include/cpu-sh3/cpu/dac.h b/arch/sh/include/cpu-sh3/cpu/dac.h
index 05fda83..98f1d15 100644
--- a/arch/sh/include/cpu-sh3/cpu/dac.h
+++ b/arch/sh/include/cpu-sh3/cpu/dac.h
@@ -17,25 +17,25 @@
 static __inline__ void sh_dac_enable(int channel)
 {
 	unsigned char v;
-	v = ctrl_inb(DACR);
+	v = __raw_readb(DACR);
 	if(channel) v |= DACR_DAOE1;
 	else v |= DACR_DAOE0;
-	ctrl_outb(v,DACR);
+	__raw_writeb(v,DACR);
 }
 
 static __inline__ void sh_dac_disable(int channel)
 {
 	unsigned char v;
-	v = ctrl_inb(DACR);
+	v = __raw_readb(DACR);
 	if(channel) v &= ~DACR_DAOE1;
 	else v &= ~DACR_DAOE0;
-	ctrl_outb(v,DACR);
+	__raw_writeb(v,DACR);
 }
 
 static __inline__ void sh_dac_output(u8 value, int channel)
 {
-	if(channel) ctrl_outb(value,DADR1);
-	else ctrl_outb(value,DADR0);
+	if(channel) __raw_writeb(value,DADR1);
+	else __raw_writeb(value,DADR0);
 }
 
 #endif /* __ASM_CPU_SH3_DAC_H */
diff --git a/arch/sh/include/cpu-sh3/cpu/dma.h b/arch/sh/include/cpu-sh3/cpu/dma.h
index 0ea15f3..207811a 100644
--- a/arch/sh/include/cpu-sh3/cpu/dma.h
+++ b/arch/sh/include/cpu-sh3/cpu/dma.h
@@ -20,8 +20,10 @@
 #define TS_32		0x00000010
 #define TS_128		0x00000018
 
-#define CHCR_TS_MASK	0x18
-#define CHCR_TS_SHIFT	3
+#define CHCR_TS_LOW_MASK	0x18
+#define CHCR_TS_LOW_SHIFT	3
+#define CHCR_TS_HIGH_MASK	0
+#define CHCR_TS_HIGH_SHIFT	0
 
 #define DMAOR_INIT	DMAOR_DME
 
@@ -36,11 +38,13 @@
 	XMIT_SZ_128BIT,
 };
 
-static unsigned int ts_shift[] __maybe_unused = {
-	[XMIT_SZ_8BIT]		= 0,
-	[XMIT_SZ_16BIT]		= 1,
-	[XMIT_SZ_32BIT]		= 2,
-	[XMIT_SZ_128BIT]	= 4,
-};
+#define TS_SHIFT {			\
+	[XMIT_SZ_8BIT]		= 0,	\
+	[XMIT_SZ_16BIT]		= 1,	\
+	[XMIT_SZ_32BIT]		= 2,	\
+	[XMIT_SZ_128BIT]	= 4,	\
+}
+
+#define TS_INDEX2VAL(i)	(((i) & 3) << CHCR_TS_LOW_SHIFT)
 
 #endif /* __ASM_CPU_SH3_DMA_H */
diff --git a/arch/sh/include/cpu-sh3/cpu/ubc.h b/arch/sh/include/cpu-sh3/cpu/ubc.h
deleted file mode 100644
index 4e6381d..0000000
--- a/arch/sh/include/cpu-sh3/cpu/ubc.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * include/asm-sh/cpu-sh3/ubc.h
- *
- * Copyright (C) 1999 Niibe Yutaka
- * Copyright (C) 2003 Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-#ifndef __ASM_CPU_SH3_UBC_H
-#define __ASM_CPU_SH3_UBC_H
-
-#if defined(CONFIG_CPU_SUBTYPE_SH7710) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7720) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7721)
-#define UBC_BARA		0xa4ffffb0
-#define UBC_BAMRA		0xa4ffffb4
-#define UBC_BBRA		0xa4ffffb8
-#define UBC_BASRA		0xffffffe4
-#define UBC_BARB		0xa4ffffa0
-#define UBC_BAMRB		0xa4ffffa4
-#define UBC_BBRB		0xa4ffffa8
-#define UBC_BASRB		0xffffffe8
-#define UBC_BDRB		0xa4ffff90
-#define UBC_BDMRB		0xa4ffff94
-#define UBC_BRCR		0xa4ffff98
-#else
-#define UBC_BARA                0xffffffb0
-#define UBC_BAMRA               0xffffffb4
-#define UBC_BBRA                0xffffffb8
-#define UBC_BASRA               0xffffffe4
-#define UBC_BARB                0xffffffa0
-#define UBC_BAMRB               0xffffffa4
-#define UBC_BBRB                0xffffffa8
-#define UBC_BASRB               0xffffffe8
-#define UBC_BDRB                0xffffff90
-#define UBC_BDMRB               0xffffff94
-#define UBC_BRCR                0xffffff98
-#endif
-
-#endif /* __ASM_CPU_SH3_UBC_H */
diff --git a/arch/sh/include/cpu-sh4/cpu/addrspace.h b/arch/sh/include/cpu-sh4/cpu/addrspace.h
index a3fa733..d51da25 100644
--- a/arch/sh/include/cpu-sh4/cpu/addrspace.h
+++ b/arch/sh/include/cpu-sh4/cpu/addrspace.h
@@ -28,6 +28,15 @@
 #define P4SEG_TLB_DATA	0xf7000000
 #define P4SEG_REG_BASE	0xff000000
 
+#define PA_AREA0	0x00000000
+#define PA_AREA1	0x04000000
+#define PA_AREA2	0x08000000
+#define PA_AREA3	0x0c000000
+#define PA_AREA4	0x10000000
+#define PA_AREA5	0x14000000
+#define PA_AREA6	0x18000000
+#define PA_AREA7	0x1c000000
+
 #define PA_AREA5_IO	0xb4000000	/* Area 5 IO Memory */
 #define PA_AREA6_IO	0xb8000000	/* Area 6 IO Memory */
 
diff --git a/arch/sh/include/cpu-sh4/cpu/dma-sh4a.h b/arch/sh/include/cpu-sh4/cpu/dma-sh4a.h
index c4ed660..e734ea4 100644
--- a/arch/sh/include/cpu-sh4/cpu/dma-sh4a.h
+++ b/arch/sh/include/cpu-sh4/cpu/dma-sh4a.h
@@ -2,22 +2,38 @@
 #define __ASM_SH_CPU_SH4_DMA_SH7780_H
 
 #if defined(CONFIG_CPU_SUBTYPE_SH7343) || \
-	defined(CONFIG_CPU_SUBTYPE_SH7722) || \
 	defined(CONFIG_CPU_SUBTYPE_SH7730)
 #define DMTE0_IRQ	48
 #define DMTE4_IRQ	76
 #define DMAE0_IRQ	78	/* DMA Error IRQ*/
 #define SH_DMAC_BASE0	0xFE008020
-#define SH_DMARS_BASE	0xFE009000
+#define SH_DMARS_BASE0	0xFE009000
+#define CHCR_TS_LOW_MASK	0x00000018
+#define CHCR_TS_LOW_SHIFT	3
+#define CHCR_TS_HIGH_MASK	0
+#define CHCR_TS_HIGH_SHIFT	0
+#elif defined(CONFIG_CPU_SUBTYPE_SH7722)
+#define DMTE0_IRQ	48
+#define DMTE4_IRQ	76
+#define DMAE0_IRQ	78	/* DMA Error IRQ*/
+#define SH_DMAC_BASE0	0xFE008020
+#define SH_DMARS_BASE0	0xFE009000
+#define CHCR_TS_LOW_MASK	0x00000018
+#define CHCR_TS_LOW_SHIFT	3
+#define CHCR_TS_HIGH_MASK	0x00300000
+#define CHCR_TS_HIGH_SHIFT	20
 #elif defined(CONFIG_CPU_SUBTYPE_SH7763) || \
 	defined(CONFIG_CPU_SUBTYPE_SH7764)
 #define DMTE0_IRQ	34
 #define DMTE4_IRQ	44
 #define DMAE0_IRQ	38
 #define SH_DMAC_BASE0	0xFF608020
-#define SH_DMARS_BASE	0xFF609000
-#elif defined(CONFIG_CPU_SUBTYPE_SH7723) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7724)
+#define SH_DMARS_BASE0	0xFF609000
+#define CHCR_TS_LOW_MASK	0x00000018
+#define CHCR_TS_LOW_SHIFT	3
+#define CHCR_TS_HIGH_MASK	0
+#define CHCR_TS_HIGH_SHIFT	0
+#elif defined(CONFIG_CPU_SUBTYPE_SH7723)
 #define DMTE0_IRQ	48	/* DMAC0A*/
 #define DMTE4_IRQ	76	/* DMAC0B */
 #define DMTE6_IRQ	40
@@ -29,7 +45,29 @@
 #define DMAE1_IRQ	74	/* DMA Error IRQ*/
 #define SH_DMAC_BASE0	0xFE008020
 #define SH_DMAC_BASE1	0xFDC08020
-#define SH_DMARS_BASE	0xFDC09000
+#define SH_DMARS_BASE0	0xFDC09000
+#define CHCR_TS_LOW_MASK	0x00000018
+#define CHCR_TS_LOW_SHIFT	3
+#define CHCR_TS_HIGH_MASK	0
+#define CHCR_TS_HIGH_SHIFT	0
+#elif defined(CONFIG_CPU_SUBTYPE_SH7724)
+#define DMTE0_IRQ	48	/* DMAC0A*/
+#define DMTE4_IRQ	76	/* DMAC0B */
+#define DMTE6_IRQ	40
+#define DMTE8_IRQ	42	/* DMAC1A */
+#define DMTE9_IRQ	43
+#define DMTE10_IRQ	72	/* DMAC1B */
+#define DMTE11_IRQ	73
+#define DMAE0_IRQ	78	/* DMA Error IRQ*/
+#define DMAE1_IRQ	74	/* DMA Error IRQ*/
+#define SH_DMAC_BASE0	0xFE008020
+#define SH_DMAC_BASE1	0xFDC08020
+#define SH_DMARS_BASE0	0xFE009000
+#define SH_DMARS_BASE1	0xFDC09000
+#define CHCR_TS_LOW_MASK	0x00000018
+#define CHCR_TS_LOW_SHIFT	3
+#define CHCR_TS_HIGH_MASK	0x00600000
+#define CHCR_TS_HIGH_SHIFT	21
 #elif defined(CONFIG_CPU_SUBTYPE_SH7780)
 #define DMTE0_IRQ	34
 #define DMTE4_IRQ	44
@@ -41,7 +79,11 @@
 #define DMAE0_IRQ	38	/* DMA Error IRQ */
 #define SH_DMAC_BASE0	0xFC808020
 #define SH_DMAC_BASE1	0xFC818020
-#define SH_DMARS_BASE	0xFC809000
+#define SH_DMARS_BASE0	0xFC809000
+#define CHCR_TS_LOW_MASK	0x00000018
+#define CHCR_TS_LOW_SHIFT	3
+#define CHCR_TS_HIGH_MASK	0
+#define CHCR_TS_HIGH_SHIFT	0
 #else /* SH7785 */
 #define DMTE0_IRQ	33
 #define DMTE4_IRQ	37
@@ -54,18 +96,17 @@
 #define DMAE1_IRQ	58	/* DMA Error IRQ1 */
 #define SH_DMAC_BASE0	0xFC808020
 #define SH_DMAC_BASE1	0xFCC08020
-#define SH_DMARS_BASE	0xFC809000
+#define SH_DMARS_BASE0	0xFC809000
+#define CHCR_TS_LOW_MASK	0x00000018
+#define CHCR_TS_LOW_SHIFT	3
+#define CHCR_TS_HIGH_MASK	0
+#define CHCR_TS_HIGH_SHIFT	0
 #endif
 
-#define REQ_HE	0x000000C0
-#define REQ_H	0x00000080
-#define REQ_LE	0x00000040
-#define TM_BURST 0x0000020
-#define TS_8	0x00000000
-#define TS_16	0x00000008
-#define TS_32	0x00000010
-#define TS_16BLK	0x00000018
-#define TS_32BLK	0x00100000
+#define REQ_HE		0x000000C0
+#define REQ_H		0x00000080
+#define REQ_LE		0x00000040
+#define TM_BURST	0x00000020
 
 /*
  * The SuperH DMAC supports a number of transmit sizes, we list them here,
@@ -74,22 +115,31 @@
  * Defaults to a 64-bit transfer size.
  */
 enum {
-	XMIT_SZ_8BIT,
-	XMIT_SZ_16BIT,
-	XMIT_SZ_32BIT,
-	XMIT_SZ_128BIT,
-	XMIT_SZ_256BIT,
+	XMIT_SZ_8BIT		= 0,
+	XMIT_SZ_16BIT		= 1,
+	XMIT_SZ_32BIT		= 2,
+	XMIT_SZ_64BIT		= 7,
+	XMIT_SZ_128BIT		= 3,
+	XMIT_SZ_256BIT		= 4,
+	XMIT_SZ_128BIT_BLK	= 0xb,
+	XMIT_SZ_256BIT_BLK	= 0xc,
 };
 
 /*
  * The DMA count is defined as the number of bytes to transfer.
  */
-static unsigned int ts_shift[] __maybe_unused = {
-	[XMIT_SZ_8BIT]		= 0,
-	[XMIT_SZ_16BIT]		= 1,
-	[XMIT_SZ_32BIT]		= 2,
-	[XMIT_SZ_128BIT]	= 4,
-	[XMIT_SZ_256BIT]	= 5,
-};
+#define TS_SHIFT {			\
+	[XMIT_SZ_8BIT]		= 0,	\
+	[XMIT_SZ_16BIT]		= 1,	\
+	[XMIT_SZ_32BIT]		= 2,	\
+	[XMIT_SZ_64BIT]		= 3,	\
+	[XMIT_SZ_128BIT]	= 4,	\
+	[XMIT_SZ_256BIT]	= 5,	\
+	[XMIT_SZ_128BIT_BLK]	= 4,	\
+	[XMIT_SZ_256BIT_BLK]	= 5,	\
+}
+
+#define TS_INDEX2VAL(i)	((((i) & 3) << CHCR_TS_LOW_SHIFT) | \
+			 ((((i) >> 2) & 3) << CHCR_TS_HIGH_SHIFT))
 
 #endif /* __ASM_SH_CPU_SH4_DMA_SH7780_H */
diff --git a/arch/sh/include/cpu-sh4/cpu/dma.h b/arch/sh/include/cpu-sh4/cpu/dma.h
index bcb3024..114a369 100644
--- a/arch/sh/include/cpu-sh4/cpu/dma.h
+++ b/arch/sh/include/cpu-sh4/cpu/dma.h
@@ -6,8 +6,6 @@
 #ifdef CONFIG_CPU_SH4A
 
 #define DMAOR_INIT	(DMAOR_DME)
-#define CHCR_TS_MASK	0x18
-#define CHCR_TS_SHIFT	3
 
 #include <cpu/dma-sh4a.h>
 #else /* CONFIG_CPU_SH4A */
@@ -29,8 +27,10 @@
 #define TS_32		0x00000030
 #define TS_64		0x00000000
 
-#define CHCR_TS_MASK	0x70
-#define CHCR_TS_SHIFT	4
+#define CHCR_TS_LOW_MASK	0x70
+#define CHCR_TS_LOW_SHIFT	4
+#define CHCR_TS_HIGH_MASK	0
+#define CHCR_TS_HIGH_SHIFT	0
 
 #define DMAOR_COD	0x00000008
 
@@ -41,23 +41,26 @@
  * Defaults to a 64-bit transfer size.
  */
 enum {
-	XMIT_SZ_64BIT,
-	XMIT_SZ_8BIT,
-	XMIT_SZ_16BIT,
-	XMIT_SZ_32BIT,
-	XMIT_SZ_256BIT,
+	XMIT_SZ_8BIT	= 1,
+	XMIT_SZ_16BIT	= 2,
+	XMIT_SZ_32BIT	= 3,
+	XMIT_SZ_64BIT	= 0,
+	XMIT_SZ_256BIT	= 4,
 };
 
 /*
  * The DMA count is defined as the number of bytes to transfer.
  */
-static unsigned int ts_shift[] __maybe_unused = {
-	[XMIT_SZ_64BIT]		= 3,
-	[XMIT_SZ_8BIT]		= 0,
-	[XMIT_SZ_16BIT]		= 1,
-	[XMIT_SZ_32BIT]		= 2,
-	[XMIT_SZ_256BIT]	= 5,
-};
+#define TS_SHIFT {			\
+	[XMIT_SZ_8BIT]		= 0,	\
+	[XMIT_SZ_16BIT]		= 1,	\
+	[XMIT_SZ_32BIT]		= 2,	\
+	[XMIT_SZ_64BIT]		= 3,	\
+	[XMIT_SZ_256BIT]	= 5,	\
+}
+
+#define TS_INDEX2VAL(i)	(((i) & 7) << CHCR_TS_LOW_SHIFT)
+
 #endif
 
 #endif /* __ASM_CPU_SH4_DMA_H */
diff --git a/arch/sh/include/cpu-sh4/cpu/mmu_context.h b/arch/sh/include/cpu-sh4/cpu/mmu_context.h
index 3ce7ef6..03ea75c 100644
--- a/arch/sh/include/cpu-sh4/cpu/mmu_context.h
+++ b/arch/sh/include/cpu-sh4/cpu/mmu_context.h
@@ -25,6 +25,10 @@
 
 #define MMUCR_TI		(1<<2)
 
+#define MMUCR_URB		0x00FC0000
+#define MMUCR_URB_SHIFT		18
+#define MMUCR_URB_NENTRIES	64
+
 #if defined(CONFIG_32BIT) && defined(CONFIG_CPU_SUBTYPE_ST40)
 #define MMUCR_SE		(1 << 4)
 #else
diff --git a/arch/sh/include/cpu-sh4/cpu/sq.h b/arch/sh/include/cpu-sh4/cpu/sq.h
index 586d649..74716ba 100644
--- a/arch/sh/include/cpu-sh4/cpu/sq.h
+++ b/arch/sh/include/cpu-sh4/cpu/sq.h
@@ -12,6 +12,7 @@
 #define __ASM_CPU_SH4_SQ_H
 
 #include <asm/addrspace.h>
+#include <asm/page.h>
 
 /*
  * Store queues range from e0000000-e3fffffc, allowing approx. 64MB to be
@@ -28,7 +29,7 @@
 
 /* arch/sh/kernel/cpu/sh4/sq.c */
 unsigned long sq_remap(unsigned long phys, unsigned int size,
-		       const char *name, unsigned long flags);
+		       const char *name, pgprot_t prot);
 void sq_unmap(unsigned long vaddr);
 void sq_flush_range(unsigned long start, unsigned int len);
 
diff --git a/arch/sh/include/cpu-sh4/cpu/ubc.h b/arch/sh/include/cpu-sh4/cpu/ubc.h
deleted file mode 100644
index c86e170..0000000
--- a/arch/sh/include/cpu-sh4/cpu/ubc.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * include/asm-sh/cpu-sh4/ubc.h
- *
- * Copyright (C) 1999 Niibe Yutaka
- * Copyright (C) 2003 Paul Mundt
- * Copyright (C) 2006 Lineo Solutions Inc. support SH4A UBC
- *
- * 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_CPU_SH4_UBC_H
-#define __ASM_CPU_SH4_UBC_H
-
-#if defined(CONFIG_CPU_SH4A)
-#define UBC_CBR0		0xff200000
-#define UBC_CRR0		0xff200004
-#define UBC_CAR0		0xff200008
-#define UBC_CAMR0		0xff20000c
-#define UBC_CBR1		0xff200020
-#define UBC_CRR1		0xff200024
-#define UBC_CAR1		0xff200028
-#define UBC_CAMR1		0xff20002c
-#define UBC_CDR1		0xff200030
-#define UBC_CDMR1		0xff200034
-#define UBC_CETR1		0xff200038
-#define UBC_CCMFR		0xff200600
-#define UBC_CBCR		0xff200620
-
-/* CBR	*/
-#define UBC_CBR_AIE		(0x01<<30)
-#define UBC_CBR_ID_INST		(0x01<<4)
-#define UBC_CBR_RW_READ		(0x01<<1)
-#define UBC_CBR_CE		(0x01)
-
-#define	UBC_CBR_AIV_MASK	(0x00FF0000)
-#define	UBC_CBR_AIV_SHIFT	(16)
-#define UBC_CBR_AIV_SET(asid)	(((asid)<<UBC_CBR_AIV_SHIFT) & UBC_CBR_AIV_MASK)
-
-#define UBC_CBR_INIT		0x20000000
-
-/* CRR	*/
-#define UBC_CRR_RES		(0x01<<13)
-#define UBC_CRR_PCB		(0x01<<1)
-#define UBC_CRR_BIE		(0x01)
-
-#define UBC_CRR_INIT		0x00002000
-
-#else	/* CONFIG_CPU_SH4 */
-#define UBC_BARA		0xff200000
-#define UBC_BAMRA		0xff200004
-#define UBC_BBRA		0xff200008
-#define UBC_BASRA		0xff000014
-#define UBC_BARB		0xff20000c
-#define UBC_BAMRB		0xff200010
-#define UBC_BBRB		0xff200014
-#define UBC_BASRB		0xff000018
-#define UBC_BDRB		0xff200018
-#define UBC_BDMRB		0xff20001c
-#define UBC_BRCR		0xff200020
-#endif	/* CONFIG_CPU_SH4 */
-
-#endif /* __ASM_CPU_SH4_UBC_H */
-
diff --git a/arch/sh/include/mach-common/mach/magicpanelr2.h b/arch/sh/include/mach-common/mach/magicpanelr2.h
index c644a77..183a2f7 100644
--- a/arch/sh/include/mach-common/mach/magicpanelr2.h
+++ b/arch/sh/include/mach-common/mach/magicpanelr2.h
@@ -19,12 +19,12 @@
 #include <asm/io_generic.h>
 
 
-#define SETBITS_OUTB(mask, reg)   ctrl_outb(ctrl_inb(reg) | mask, reg)
-#define SETBITS_OUTW(mask, reg)   ctrl_outw(ctrl_inw(reg) | mask, reg)
-#define SETBITS_OUTL(mask, reg)   ctrl_outl(ctrl_inl(reg) | mask, reg)
-#define CLRBITS_OUTB(mask, reg)   ctrl_outb(ctrl_inb(reg) & ~mask, reg)
-#define CLRBITS_OUTW(mask, reg)   ctrl_outw(ctrl_inw(reg) & ~mask, reg)
-#define CLRBITS_OUTL(mask, reg)   ctrl_outl(ctrl_inl(reg) & ~mask, reg)
+#define SETBITS_OUTB(mask, reg)   __raw_writeb(__raw_readb(reg) | mask, reg)
+#define SETBITS_OUTW(mask, reg)   __raw_writew(__raw_readw(reg) | mask, reg)
+#define SETBITS_OUTL(mask, reg)   __raw_writel(__raw_readl(reg) | mask, reg)
+#define CLRBITS_OUTB(mask, reg)   __raw_writeb(__raw_readb(reg) & ~mask, reg)
+#define CLRBITS_OUTW(mask, reg)   __raw_writew(__raw_readw(reg) & ~mask, reg)
+#define CLRBITS_OUTL(mask, reg)   __raw_writel(__raw_readl(reg) & ~mask, reg)
 
 
 #define PA_LED          PORT_PADR      /* LED */
diff --git a/arch/sh/include/mach-dreamcast/mach/sysasic.h b/arch/sh/include/mach-dreamcast/mach/sysasic.h
index f334266..58f710e 100644
--- a/arch/sh/include/mach-dreamcast/mach/sysasic.h
+++ b/arch/sh/include/mach-dreamcast/mach/sysasic.h
@@ -39,5 +39,10 @@
 
 #define HW_EVENT_IRQ_MAX (HW_EVENT_IRQ_BASE + 95)
 
+/* arch/sh/boards/mach-dreamcast/irq.c */
+extern int systemasic_irq_demux(int);
+extern void systemasic_irq_init(void);
+extern void aica_time_init(void);
+
 #endif /* __ASM_SH_DREAMCAST_SYSASIC_H */
 
diff --git a/arch/sh/include/mach-sdk7786/mach/fpga.h b/arch/sh/include/mach-sdk7786/mach/fpga.h
new file mode 100644
index 0000000..2120d67
--- /dev/null
+++ b/arch/sh/include/mach-sdk7786/mach/fpga.h
@@ -0,0 +1,114 @@
+#ifndef __MACH_SDK7786_FPGA_H
+#define __MACH_SDK7786_FPGA_H
+
+#include <linux/io.h>
+#include <linux/types.h>
+#include <linux/bitops.h>
+
+#define SRSTR		0x000
+#define  SRSTR_MAGIC	0x1971	/* Fixed magical read value */
+
+#define INTASR		0x010
+#define INTAMR		0x020
+#define MODSWR		0x030
+#define INTTESTR	0x040
+#define SYSSR		0x050
+#define NRGPR		0x060
+#define NMISR		0x070
+
+#define NMIMR		0x080
+#define  NMIMR_MAN_NMIM	BIT(0)	/* Manual NMI mask */
+#define  NMIMR_AUX_NMIM	BIT(1)	/* Auxiliary NMI mask */
+
+#define INTBSR		0x090
+#define INTBMR		0x0a0
+#define USRLEDR		0x0b0
+#define MAPSWR		0x0c0
+#define FPGAVR		0x0d0
+#define FPGADR		0x0e0
+#define PCBRR		0x0f0
+#define RSR		0x100
+#define EXTASR		0x110
+#define SPCAR		0x120
+#define INTMSR		0x130
+#define PCIECR		0x140
+#define FAER		0x150
+#define USRGPIR		0x160
+/* 0x170 reserved */
+#define LCLASR		0x180
+
+#define SBCR		0x190
+#define  SCBR_I2CMEN	BIT(0)	/* FPGA I2C master enable */
+#define  SCBR_I2CCEN	BIT(1)	/* CPU I2C master enable */
+
+#define PWRCR		0x1a0
+#define SPCBR		0x1b0
+#define SPICR		0x1c0
+#define SPIDR		0x1d0
+#define I2CCR		0x1e0
+#define I2CDR		0x1f0
+#define FPGACR		0x200
+#define IASELR1		0x210
+#define IASELR2		0x220
+#define IASELR3		0x230
+#define IASELR4		0x240
+#define IASELR5		0x250
+#define IASELR6		0x260
+#define IASELR7		0x270
+#define IASELR8		0x280
+#define IASELR9		0x290
+#define IASELR10	0x2a0
+#define IASELR11	0x2b0
+#define IASELR12	0x2c0
+#define IASELR13	0x2d0
+#define IASELR14	0x2e0
+#define IASELR15	0x2f0
+/* 0x300 reserved */
+#define IBSELR1		0x310
+#define IBSELR2		0x320
+#define IBSELR3		0x330
+#define IBSELR4		0x340
+#define IBSELR5		0x350
+#define IBSELR6		0x360
+#define IBSELR7		0x370
+#define IBSELR8		0x380
+#define IBSELR9		0x390
+#define IBSELR10	0x3a0
+#define IBSELR11	0x3b0
+#define IBSELR12	0x3c0
+#define IBSELR13	0x3d0
+#define IBSELR14	0x3e0
+#define IBSELR15	0x3f0
+#define USRACR		0x400
+#define BEEPR		0x410
+#define USRLCDR		0x420
+#define SMBCR		0x430
+#define SMBDR		0x440
+#define USBCR		0x450
+#define AMSR		0x460
+#define ACCR		0x470
+#define SDIFCR		0x480
+
+/* arch/sh/boards/mach-sdk7786/fpga.c */
+extern void __iomem *sdk7786_fpga_base;
+extern void sdk7786_fpga_init(void);
+
+#define SDK7786_FPGA_REGADDR(reg)	(sdk7786_fpga_base + (reg))
+
+/*
+ * A convenience wrapper from register offset to internal I2C address,
+ * when the FPGA is in I2C slave mode.
+ */
+#define SDK7786_FPGA_I2CADDR(reg)	((reg) >> 3)
+
+static inline u16 fpga_read_reg(unsigned int reg)
+{
+	return ioread16(sdk7786_fpga_base + reg);
+}
+
+static inline void fpga_write_reg(u16 val, unsigned int reg)
+{
+	iowrite16(val, sdk7786_fpga_base + reg);
+}
+
+#endif /* __MACH_SDK7786_FPGA_H */
diff --git a/arch/sh/include/mach-sdk7786/mach/irq.h b/arch/sh/include/mach-sdk7786/mach/irq.h
new file mode 100644
index 0000000..0f58463
--- /dev/null
+++ b/arch/sh/include/mach-sdk7786/mach/irq.h
@@ -0,0 +1,7 @@
+#ifndef __MACH_SDK7786_IRQ_H
+#define __MACH_SDK7786_IRQ_H
+
+/* arch/sh/boards/mach-sdk7786/irq.c */
+extern void sdk7786_init_irq(void);
+
+#endif /* __MACH_SDK7786_IRQ_H */
diff --git a/arch/sh/include/mach-se/mach/se7343.h b/arch/sh/include/mach-se/mach/se7343.h
index 749914b..8d8170d 100644
--- a/arch/sh/include/mach-se/mach/se7343.h
+++ b/arch/sh/include/mach-se/mach/se7343.h
@@ -94,26 +94,26 @@
 
 #define PORT_DRVCR	0xA4050180
 
-#define PORT_PADR  	0xA4050120
-#define PORT_PBDR  	0xA4050122
-#define PORT_PCDR  	0xA4050124
-#define PORT_PDDR  	0xA4050126
-#define PORT_PEDR  	0xA4050128
-#define PORT_PFDR  	0xA405012A
-#define PORT_PGDR  	0xA405012C
-#define PORT_PHDR  	0xA405012E
-#define PORT_PJDR  	0xA4050130
-#define PORT_PKDR  	0xA4050132
-#define PORT_PLDR  	0xA4050134
-#define PORT_PMDR  	0xA4050136
-#define PORT_PNDR  	0xA4050138
-#define PORT_PQDR  	0xA405013A
-#define PORT_PRDR  	0xA405013C
-#define PORT_PTDR  	0xA4050160
-#define PORT_PUDR  	0xA4050162
-#define PORT_PVDR  	0xA4050164
-#define PORT_PWDR  	0xA4050166
-#define PORT_PYDR  	0xA4050168
+#define PORT_PADR	0xA4050120
+#define PORT_PBDR	0xA4050122
+#define PORT_PCDR	0xA4050124
+#define PORT_PDDR	0xA4050126
+#define PORT_PEDR	0xA4050128
+#define PORT_PFDR	0xA405012A
+#define PORT_PGDR	0xA405012C
+#define PORT_PHDR	0xA405012E
+#define PORT_PJDR	0xA4050130
+#define PORT_PKDR	0xA4050132
+#define PORT_PLDR	0xA4050134
+#define PORT_PMDR	0xA4050136
+#define PORT_PNDR	0xA4050138
+#define PORT_PQDR	0xA405013A
+#define PORT_PRDR	0xA405013C
+#define PORT_PTDR	0xA4050160
+#define PORT_PUDR	0xA4050162
+#define PORT_PVDR	0xA4050164
+#define PORT_PWDR	0xA4050166
+#define PORT_PYDR	0xA4050168
 
 #define FPGA_IN		0xb1400000
 #define FPGA_OUT	0xb1400002
@@ -133,18 +133,10 @@
 #define SE7343_FPGA_IRQ_UARTB	11
 
 #define SE7343_FPGA_IRQ_NR	12
-#define SE7343_FPGA_IRQ_BASE	120
-
-#define MRSHPC_IRQ3    	(SE7343_FPGA_IRQ_BASE + SE7343_FPGA_IRQ_MRSHPC3)
-#define MRSHPC_IRQ2    	(SE7343_FPGA_IRQ_BASE + SE7343_FPGA_IRQ_MRSHPC2)
-#define MRSHPC_IRQ1    	(SE7343_FPGA_IRQ_BASE + SE7343_FPGA_IRQ_MRSHPC1)
-#define MRSHPC_IRQ0    	(SE7343_FPGA_IRQ_BASE + SE7343_FPGA_IRQ_MRSHPC0)
-#define SMC_IRQ		(SE7343_FPGA_IRQ_BASE + SE7343_FPGA_IRQ_SMC)
-#define USB_IRQ		(SE7343_FPGA_IRQ_BASE + SE7343_FPGA_IRQ_USB)
-#define UARTA_IRQ	(SE7343_FPGA_IRQ_BASE + SE7343_FPGA_IRQ_UARTA)
-#define UARTB_IRQ	(SE7343_FPGA_IRQ_BASE + SE7343_FPGA_IRQ_UARTB)
 
 /* arch/sh/boards/se/7343/irq.c */
+extern unsigned int se7343_fpga_irq[];
+
 void init_7343se_IRQ(void);
 
 #endif  /* __ASM_SH_HITACHI_SE7343_H */
diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile
index 0d587da..02fd3ae 100644
--- a/arch/sh/kernel/Makefile
+++ b/arch/sh/kernel/Makefile
@@ -13,8 +13,9 @@
 
 obj-y	:= debugtraps.o dma-nommu.o dumpstack.o 			\
 	   idle.o io.o io_generic.o irq.o				\
-	   irq_$(BITS).o machvec.o nmi_debug.o process_$(BITS).o 	\
-	   ptrace_$(BITS).o return_address.o				\
+	   irq_$(BITS).o machvec.o nmi_debug.o process.o		\
+	   process_$(BITS).o ptrace_$(BITS).o				\
+	   reboot.o return_address.o					\
 	   setup.o signal_$(BITS).o sys_sh.o sys_sh$(BITS).o		\
 	   syscalls_$(BITS).o time.o topology.o traps.o			\
 	   traps_$(BITS).o unwinder.o
@@ -22,7 +23,7 @@
 obj-y				+= cpu/
 obj-$(CONFIG_VSYSCALL)		+= vsyscall/
 obj-$(CONFIG_SMP)		+= smp.o
-obj-$(CONFIG_SH_STANDARD_BIOS)	+= sh_bios.o early_printk.o
+obj-$(CONFIG_SH_STANDARD_BIOS)	+= sh_bios.o
 obj-$(CONFIG_KGDB)		+= kgdb.o
 obj-$(CONFIG_SH_CPU_FREQ)	+= cpufreq.o
 obj-$(CONFIG_MODULES)		+= sh_ksyms_$(BITS).o module.o
@@ -39,6 +40,7 @@
 obj-$(CONFIG_DWARF_UNWINDER)	+= dwarf.o
 obj-$(CONFIG_PERF_EVENTS)	+= perf_event.o perf_callchain.o
 
+obj-$(CONFIG_HAVE_HW_BREAKPOINT)		+= hw_breakpoint.o
 obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)	+= localtimer.o
 
 EXTRA_CFLAGS += -Werror
diff --git a/arch/sh/kernel/cpu/Makefile b/arch/sh/kernel/cpu/Makefile
index d97c803..0e48bc6 100644
--- a/arch/sh/kernel/cpu/Makefile
+++ b/arch/sh/kernel/cpu/Makefile
@@ -17,5 +17,7 @@
 
 obj-$(CONFIG_SH_ADC)		+= adc.o
 obj-$(CONFIG_SH_CLK_CPG)	+= clock-cpg.o
+obj-$(CONFIG_SH_FPU)		+= fpu.o
+obj-$(CONFIG_SH_FPU_EMU)	+= fpu.o
 
 obj-y	+= irq/ init.o clock.o hwblk.o
diff --git a/arch/sh/kernel/cpu/adc.c b/arch/sh/kernel/cpu/adc.c
index da3d687..d307571 100644
--- a/arch/sh/kernel/cpu/adc.c
+++ b/arch/sh/kernel/cpu/adc.c
@@ -18,19 +18,19 @@
 
 	off = (channel & 0x03) << 2;
 
-	csr = ctrl_inb(ADCSR);
+	csr = __raw_readb(ADCSR);
 	csr = channel | ADCSR_ADST | ADCSR_CKS;
-	ctrl_outb(csr, ADCSR);
+	__raw_writeb(csr, ADCSR);
 
 	do {
-		csr = ctrl_inb(ADCSR);
+		csr = __raw_readb(ADCSR);
 	} while ((csr & ADCSR_ADF) == 0);
 
 	csr &= ~(ADCSR_ADF | ADCSR_ADST);
-	ctrl_outb(csr, ADCSR);
+	__raw_writeb(csr, ADCSR);
 
-	return (((ctrl_inb(ADDRAH + off) << 8) |
-		ctrl_inb(ADDRAL + off)) >> 6);
+	return (((__raw_readb(ADDRAH + off) << 8) |
+		__raw_readb(ADDRAL + off)) >> 6);
 }
 
 EXPORT_SYMBOL(adc_single);
diff --git a/arch/sh/kernel/cpu/clock-cpg.c b/arch/sh/kernel/cpu/clock-cpg.c
index 6dfe2cc..eed5eaf 100644
--- a/arch/sh/kernel/cpu/clock-cpg.c
+++ b/arch/sh/kernel/cpu/clock-cpg.c
@@ -149,7 +149,8 @@
 
 static unsigned long sh_clk_div4_recalc(struct clk *clk)
 {
-	struct clk_div_mult_table *table = clk->priv;
+	struct clk_div4_table *d4t = clk->priv;
+	struct clk_div_mult_table *table = d4t->div_mult_table;
 	unsigned int idx;
 
 	clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
@@ -160,17 +161,90 @@
 	return clk->freq_table[idx].frequency;
 }
 
+static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent)
+{
+	struct clk_div4_table *d4t = clk->priv;
+	struct clk_div_mult_table *table = d4t->div_mult_table;
+	u32 value;
+	int ret;
+
+	if (!strcmp("pll_clk", parent->name))
+		value = __raw_readl(clk->enable_reg) & ~(1 << 7);
+	else
+		value = __raw_readl(clk->enable_reg) | (1 << 7);
+
+	ret = clk_reparent(clk, parent);
+	if (ret < 0)
+		return ret;
+
+	__raw_writel(value, clk->enable_reg);
+
+	/* Rebiuld the frequency table */
+	clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
+			     table, &clk->arch_flags);
+
+	return 0;
+}
+
+static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate, int algo_id)
+{
+	struct clk_div4_table *d4t = clk->priv;
+	unsigned long value;
+	int idx = clk_rate_table_find(clk, clk->freq_table, rate);
+	if (idx < 0)
+		return idx;
+
+	value = __raw_readl(clk->enable_reg);
+	value &= ~(0xf << clk->enable_bit);
+	value |= (idx << clk->enable_bit);
+	__raw_writel(value, clk->enable_reg);
+
+	if (d4t->kick)
+		d4t->kick(clk);
+
+	return 0;
+}
+
+static int sh_clk_div4_enable(struct clk *clk)
+{
+	__raw_writel(__raw_readl(clk->enable_reg) & ~(1 << 8), clk->enable_reg);
+	return 0;
+}
+
+static void sh_clk_div4_disable(struct clk *clk)
+{
+	__raw_writel(__raw_readl(clk->enable_reg) | (1 << 8), clk->enable_reg);
+}
+
 static struct clk_ops sh_clk_div4_clk_ops = {
 	.recalc		= sh_clk_div4_recalc,
+	.set_rate	= sh_clk_div4_set_rate,
 	.round_rate	= sh_clk_div_round_rate,
 };
 
-int __init sh_clk_div4_register(struct clk *clks, int nr,
-				struct clk_div_mult_table *table)
+static struct clk_ops sh_clk_div4_enable_clk_ops = {
+	.recalc		= sh_clk_div4_recalc,
+	.set_rate	= sh_clk_div4_set_rate,
+	.round_rate	= sh_clk_div_round_rate,
+	.enable		= sh_clk_div4_enable,
+	.disable	= sh_clk_div4_disable,
+};
+
+static struct clk_ops sh_clk_div4_reparent_clk_ops = {
+	.recalc		= sh_clk_div4_recalc,
+	.set_rate	= sh_clk_div4_set_rate,
+	.round_rate	= sh_clk_div_round_rate,
+	.enable		= sh_clk_div4_enable,
+	.disable	= sh_clk_div4_disable,
+	.set_parent	= sh_clk_div4_set_parent,
+};
+
+static int __init sh_clk_div4_register_ops(struct clk *clks, int nr,
+			struct clk_div4_table *table, struct clk_ops *ops)
 {
 	struct clk *clkp;
 	void *freq_table;
-	int nr_divs = table->nr_divisors;
+	int nr_divs = table->div_mult_table->nr_divisors;
 	int freq_table_size = sizeof(struct cpufreq_frequency_table);
 	int ret = 0;
 	int k;
@@ -185,7 +259,7 @@
 	for (k = 0; !ret && (k < nr); k++) {
 		clkp = clks + k;
 
-		clkp->ops = &sh_clk_div4_clk_ops;
+		clkp->ops = ops;
 		clkp->id = -1;
 		clkp->priv = table;
 
@@ -198,6 +272,26 @@
 	return ret;
 }
 
+int __init sh_clk_div4_register(struct clk *clks, int nr,
+				struct clk_div4_table *table)
+{
+	return sh_clk_div4_register_ops(clks, nr, table, &sh_clk_div4_clk_ops);
+}
+
+int __init sh_clk_div4_enable_register(struct clk *clks, int nr,
+				struct clk_div4_table *table)
+{
+	return sh_clk_div4_register_ops(clks, nr, table,
+					&sh_clk_div4_enable_clk_ops);
+}
+
+int __init sh_clk_div4_reparent_register(struct clk *clks, int nr,
+				struct clk_div4_table *table)
+{
+	return sh_clk_div4_register_ops(clks, nr, table,
+					&sh_clk_div4_reparent_clk_ops);
+}
+
 #ifdef CONFIG_SH_CLK_CPG_LEGACY
 static struct clk master_clk = {
 	.name		= "master_clk",
diff --git a/arch/sh/kernel/cpu/fpu.c b/arch/sh/kernel/cpu/fpu.c
new file mode 100644
index 0000000..f059ed6
--- /dev/null
+++ b/arch/sh/kernel/cpu/fpu.c
@@ -0,0 +1,84 @@
+#include <linux/sched.h>
+#include <asm/processor.h>
+#include <asm/fpu.h>
+
+int init_fpu(struct task_struct *tsk)
+{
+	if (tsk_used_math(tsk)) {
+		if ((boot_cpu_data.flags & CPU_HAS_FPU) && tsk == current)
+			unlazy_fpu(tsk, task_pt_regs(tsk));
+		return 0;
+	}
+
+	/*
+	 * Memory allocation at the first usage of the FPU and other state.
+	 */
+	if (!tsk->thread.xstate) {
+		tsk->thread.xstate = kmem_cache_alloc(task_xstate_cachep,
+						      GFP_KERNEL);
+		if (!tsk->thread.xstate)
+			return -ENOMEM;
+	}
+
+	if (boot_cpu_data.flags & CPU_HAS_FPU) {
+		struct sh_fpu_hard_struct *fp = &tsk->thread.xstate->hardfpu;
+		memset(fp, 0, xstate_size);
+		fp->fpscr = FPSCR_INIT;
+	} else {
+		struct sh_fpu_soft_struct *fp = &tsk->thread.xstate->softfpu;
+		memset(fp, 0, xstate_size);
+		fp->fpscr = FPSCR_INIT;
+	}
+
+	set_stopped_child_used_math(tsk);
+	return 0;
+}
+
+#ifdef CONFIG_SH_FPU
+void __fpu_state_restore(void)
+{
+	struct task_struct *tsk = current;
+
+	restore_fpu(tsk);
+
+	task_thread_info(tsk)->status |= TS_USEDFPU;
+	tsk->fpu_counter++;
+}
+
+void fpu_state_restore(struct pt_regs *regs)
+{
+	struct task_struct *tsk = current;
+
+	if (unlikely(!user_mode(regs))) {
+		printk(KERN_ERR "BUG: FPU is used in kernel mode.\n");
+		BUG();
+		return;
+	}
+
+	if (!tsk_used_math(tsk)) {
+		local_irq_enable();
+		/*
+		 * does a slab alloc which can sleep
+		 */
+		if (init_fpu(tsk)) {
+			/*
+			 * ran out of memory!
+			 */
+			do_group_exit(SIGKILL);
+			return;
+		}
+		local_irq_disable();
+	}
+
+	grab_fpu(regs);
+
+	__fpu_state_restore();
+}
+
+BUILD_TRAP_HANDLER(fpu_state_restore)
+{
+	TRAP_HANDLER_DECL;
+
+	fpu_state_restore(regs);
+}
+#endif /* CONFIG_SH_FPU */
diff --git a/arch/sh/kernel/cpu/init.c b/arch/sh/kernel/cpu/init.c
index 89b4b76..c736422 100644
--- a/arch/sh/kernel/cpu/init.c
+++ b/arch/sh/kernel/cpu/init.c
@@ -24,22 +24,32 @@
 #include <asm/elf.h>
 #include <asm/io.h>
 #include <asm/smp.h>
-#ifdef CONFIG_SUPERH32
-#include <asm/ubc.h>
+#include <asm/sh_bios.h>
+
+#ifdef CONFIG_SH_FPU
+#define cpu_has_fpu	1
+#else
+#define cpu_has_fpu	0
+#endif
+
+#ifdef CONFIG_SH_DSP
+#define cpu_has_dsp	1
+#else
+#define cpu_has_dsp	0
 #endif
 
 /*
  * Generic wrapper for command line arguments to disable on-chip
  * peripherals (nofpu, nodsp, and so forth).
  */
-#define onchip_setup(x)				\
-static int x##_disabled __initdata = 0;		\
-						\
-static int __init x##_setup(char *opts)		\
-{						\
-	x##_disabled = 1;			\
-	return 1;				\
-}						\
+#define onchip_setup(x)					\
+static int x##_disabled __initdata = !cpu_has_##x;	\
+							\
+static int __init x##_setup(char *opts)			\
+{							\
+	x##_disabled = 1;				\
+	return 1;					\
+}							\
 __setup("no" __stringify(x), x##_setup);
 
 onchip_setup(fpu);
@@ -52,10 +62,10 @@
 static void __init speculative_execution_init(void)
 {
 	/* Clear RABD */
-	ctrl_outl(ctrl_inl(CPUOPM) & ~CPUOPM_RABD, CPUOPM);
+	__raw_writel(__raw_readl(CPUOPM) & ~CPUOPM_RABD, CPUOPM);
 
 	/* Flush the update */
-	(void)ctrl_inl(CPUOPM);
+	(void)__raw_readl(CPUOPM);
 	ctrl_barrier();
 }
 #else
@@ -89,7 +99,7 @@
 #endif
 
 /* 2nd-level cache init */
-void __uses_jump_to_uncached __attribute__ ((weak)) l2_cache_init(void)
+void __attribute__ ((weak)) l2_cache_init(void)
 {
 }
 
@@ -97,12 +107,12 @@
  * Generic first-level cache init
  */
 #ifdef CONFIG_SUPERH32
-static void __uses_jump_to_uncached cache_init(void)
+static void cache_init(void)
 {
 	unsigned long ccr, flags;
 
 	jump_to_uncached();
-	ccr = ctrl_inl(CCR);
+	ccr = __raw_readl(CCR);
 
 	/*
 	 * At this point we don't know whether the cache is enabled or not - a
@@ -146,7 +156,7 @@
 			for (addr = addrstart;
 			     addr < addrstart + waysize;
 			     addr += current_cpu_data.dcache.linesz)
-				ctrl_outl(0, addr);
+				__raw_writel(0, addr);
 
 			addrstart += current_cpu_data.dcache.way_incr;
 		} while (--ways);
@@ -179,7 +189,7 @@
 
 	l2_cache_init();
 
-	ctrl_outl(flags, CCR);
+	__raw_writel(flags, CCR);
 	back_to_cached();
 }
 #else
@@ -207,6 +217,18 @@
 		l2_cache_shape = -1; /* No S-cache */
 }
 
+static void __init fpu_init(void)
+{
+	/* Disable the FPU */
+	if (fpu_disabled && (current_cpu_data.flags & CPU_HAS_FPU)) {
+		printk("FPU Disabled\n");
+		current_cpu_data.flags &= ~CPU_HAS_FPU;
+	}
+
+	disable_fpu();
+	clear_used_math();
+}
+
 #ifdef CONFIG_SH_DSP
 static void __init release_dsp(void)
 {
@@ -244,28 +266,35 @@
 	if (sr & SR_DSP)
 		current_cpu_data.flags |= CPU_HAS_DSP;
 
+	/* Disable the DSP */
+	if (dsp_disabled && (current_cpu_data.flags & CPU_HAS_DSP)) {
+		printk("DSP Disabled\n");
+		current_cpu_data.flags &= ~CPU_HAS_DSP;
+	}
+
 	/* Now that we've determined the DSP status, clear the DSP bit. */
 	release_dsp();
 }
+#else
+static inline void __init dsp_init(void) { }
 #endif /* CONFIG_SH_DSP */
 
 /**
  * sh_cpu_init
  *
- * This is our initial entry point for each CPU, and is invoked on the boot
- * CPU prior to calling start_kernel(). For SMP, a combination of this and
- * start_secondary() will bring up each processor to a ready state prior
- * to hand forking the idle loop.
+ * This is our initial entry point for each CPU, and is invoked on the
+ * boot CPU prior to calling start_kernel(). For SMP, a combination of
+ * this and start_secondary() will bring up each processor to a ready
+ * state prior to hand forking the idle loop.
  *
- * We do all of the basic processor init here, including setting up the
- * caches, FPU, DSP, kicking the UBC, etc. By the time start_kernel() is
- * hit (and subsequently platform_setup()) things like determining the
- * CPU subtype and initial configuration will all be done.
+ * We do all of the basic processor init here, including setting up
+ * the caches, FPU, DSP, etc. By the time start_kernel() is hit (and
+ * subsequently platform_setup()) things like determining the CPU
+ * subtype and initial configuration will all be done.
  *
  * Each processor family is still responsible for doing its own probing
  * and cache configuration in detect_cpu_and_cache_system().
  */
-
 asmlinkage void __init sh_cpu_init(void)
 {
 	current_thread_info()->cpu = hard_smp_processor_id();
@@ -302,18 +331,8 @@
 		detect_cache_shape();
 	}
 
-	/* Disable the FPU */
-	if (fpu_disabled) {
-		printk("FPU Disabled\n");
-		current_cpu_data.flags &= ~CPU_HAS_FPU;
-	}
-
-	/* FPU initialization */
-	disable_fpu();
-	if ((current_cpu_data.flags & CPU_HAS_FPU)) {
-		current_thread_info()->status &= ~TS_USEDFPU;
-		clear_used_math();
-	}
+	fpu_init();
+	dsp_init();
 
 	/*
 	 * Initialize the per-CPU ASID cache very early, since the
@@ -321,18 +340,24 @@
 	 */
 	current_cpu_data.asid_cache = NO_CONTEXT;
 
-#ifdef CONFIG_SH_DSP
-	/* Probe for DSP */
-	dsp_init();
-
-	/* Disable the DSP */
-	if (dsp_disabled) {
-		printk("DSP Disabled\n");
-		current_cpu_data.flags &= ~CPU_HAS_DSP;
-		release_dsp();
-	}
-#endif
-
 	speculative_execution_init();
 	expmask_init();
+
+	/* Do the rest of the boot processor setup */
+	if (raw_smp_processor_id() == 0) {
+		/* Save off the BIOS VBR, if there is one */
+		sh_bios_vbr_init();
+
+		/*
+		 * Setup VBR for boot CPU. Secondary CPUs do this through
+		 * start_secondary().
+		 */
+		per_cpu_trap_init();
+
+		/*
+		 * Boot processor to setup the FP and extended state
+		 * context info.
+		 */
+		init_thread_xstate();
+	}
 }
diff --git a/arch/sh/kernel/cpu/irq/intc-sh5.c b/arch/sh/kernel/cpu/irq/intc-sh5.c
index 06e7e29..96a2395 100644
--- a/arch/sh/kernel/cpu/irq/intc-sh5.c
+++ b/arch/sh/kernel/cpu/irq/intc-sh5.c
@@ -123,7 +123,7 @@
 		bitmask = 1 << (irq - 32);
 	}
 
-	ctrl_outl(bitmask, reg);
+	__raw_writel(bitmask, reg);
 }
 
 static void disable_intc_irq(unsigned int irq)
@@ -139,7 +139,7 @@
 		bitmask = 1 << (irq - 32);
 	}
 
-	ctrl_outl(bitmask, reg);
+	__raw_writel(bitmask, reg);
 }
 
 static void mask_and_ack_intc(unsigned int irq)
@@ -170,11 +170,11 @@
 
 
 	/* Disable all interrupts and set all priorities to 0 to avoid trouble */
-	ctrl_outl(-1, INTC_INTDSB_0);
-	ctrl_outl(-1, INTC_INTDSB_1);
+	__raw_writel(-1, INTC_INTDSB_0);
+	__raw_writel(-1, INTC_INTDSB_1);
 
 	for (reg = INTC_INTPRI_0, i = 0; i < INTC_INTPRI_PREGS; i++, reg += 8)
-		ctrl_outl( NO_PRIORITY, reg);
+		__raw_writel( NO_PRIORITY, reg);
 
 
 #ifdef CONFIG_SH_CAYMAN
@@ -199,7 +199,7 @@
 			reg = INTC_ICR_SET;
 			i = IRQ_IRL0;
 		}
-		ctrl_outl(INTC_ICR_IRLM, reg);
+		__raw_writel(INTC_ICR_IRLM, reg);
 
 		/* Set interrupt priorities according to platform description */
 		for (data = 0, reg = INTC_INTPRI_0; i < NR_INTC_IRQS; i++) {
@@ -207,7 +207,7 @@
 				((i % INTC_INTPRI_PPREG) * 4);
 			if ((i % INTC_INTPRI_PPREG) == (INTC_INTPRI_PPREG - 1)) {
 				/* Upon the 7th, set Priority Register */
-				ctrl_outl(data, reg);
+				__raw_writel(data, reg);
 				data = 0;
 				reg += 8;
 			}
diff --git a/arch/sh/kernel/cpu/sh2/clock-sh7619.c b/arch/sh/kernel/cpu/sh2/clock-sh7619.c
index 4fe8631..0c9f24d 100644
--- a/arch/sh/kernel/cpu/sh2/clock-sh7619.c
+++ b/arch/sh/kernel/cpu/sh2/clock-sh7619.c
@@ -31,7 +31,7 @@
 
 static void master_clk_init(struct clk *clk)
 {
-	clk->rate *= PLL2 * pll1rate[(ctrl_inw(FREQCR) >> 8) & 7];
+	clk->rate *= PLL2 * pll1rate[(__raw_readw(FREQCR) >> 8) & 7];
 }
 
 static struct clk_ops sh7619_master_clk_ops = {
@@ -40,7 +40,7 @@
 
 static unsigned long module_clk_recalc(struct clk *clk)
 {
-	int idx = (ctrl_inw(FREQCR) & 0x0007);
+	int idx = (__raw_readw(FREQCR) & 0x0007);
 	return clk->parent->rate / pfc_divisors[idx];
 }
 
@@ -50,7 +50,7 @@
 
 static unsigned long bus_clk_recalc(struct clk *clk)
 {
-	return clk->parent->rate / pll1rate[(ctrl_inw(FREQCR) >> 8) & 7];
+	return clk->parent->rate / pll1rate[(__raw_readw(FREQCR) >> 8) & 7];
 }
 
 static struct clk_ops sh7619_bus_clk_ops = {
diff --git a/arch/sh/kernel/cpu/sh2a/clock-sh7201.c b/arch/sh/kernel/cpu/sh2a/clock-sh7201.c
index 7814c76..b26264d 100644
--- a/arch/sh/kernel/cpu/sh2a/clock-sh7201.c
+++ b/arch/sh/kernel/cpu/sh2a/clock-sh7201.c
@@ -34,7 +34,7 @@
 
 static void master_clk_init(struct clk *clk)
 {
-	return 10000000 * PLL2 * pll1rate[(ctrl_inw(FREQCR) >> 8) & 0x0007];
+	return 10000000 * PLL2 * pll1rate[(__raw_readw(FREQCR) >> 8) & 0x0007];
 }
 
 static struct clk_ops sh7201_master_clk_ops = {
@@ -43,7 +43,7 @@
 
 static unsigned long module_clk_recalc(struct clk *clk)
 {
-	int idx = (ctrl_inw(FREQCR) & 0x0007);
+	int idx = (__raw_readw(FREQCR) & 0x0007);
 	return clk->parent->rate / pfc_divisors[idx];
 }
 
@@ -53,7 +53,7 @@
 
 static unsigned long bus_clk_recalc(struct clk *clk)
 {
-	int idx = (ctrl_inw(FREQCR) & 0x0007);
+	int idx = (__raw_readw(FREQCR) & 0x0007);
 	return clk->parent->rate / pfc_divisors[idx];
 }
 
@@ -63,7 +63,7 @@
 
 static unsigned long cpu_clk_recalc(struct clk *clk)
 {
-	int idx = ((ctrl_inw(FREQCR) >> 4) & 0x0007);
+	int idx = ((__raw_readw(FREQCR) >> 4) & 0x0007);
 	return clk->parent->rate / ifc_divisors[idx];
 }
 
diff --git a/arch/sh/kernel/cpu/sh2a/clock-sh7203.c b/arch/sh/kernel/cpu/sh2a/clock-sh7203.c
index 9409869..7e75d8f 100644
--- a/arch/sh/kernel/cpu/sh2a/clock-sh7203.c
+++ b/arch/sh/kernel/cpu/sh2a/clock-sh7203.c
@@ -39,7 +39,7 @@
 
 static void master_clk_init(struct clk *clk)
 {
-	clk->rate *= pll1rate[(ctrl_inw(FREQCR) >> 8) & 0x0003] * PLL2 ;
+	clk->rate *= pll1rate[(__raw_readw(FREQCR) >> 8) & 0x0003] * PLL2 ;
 }
 
 static struct clk_ops sh7203_master_clk_ops = {
@@ -48,7 +48,7 @@
 
 static unsigned long module_clk_recalc(struct clk *clk)
 {
-	int idx = (ctrl_inw(FREQCR) & 0x0007);
+	int idx = (__raw_readw(FREQCR) & 0x0007);
 	return clk->parent->rate / pfc_divisors[idx];
 }
 
@@ -58,7 +58,7 @@
 
 static unsigned long bus_clk_recalc(struct clk *clk)
 {
-	int idx = (ctrl_inw(FREQCR) & 0x0007);
+	int idx = (__raw_readw(FREQCR) & 0x0007);
 	return clk->parent->rate / pfc_divisors[idx-2];
 }
 
diff --git a/arch/sh/kernel/cpu/sh2a/clock-sh7206.c b/arch/sh/kernel/cpu/sh2a/clock-sh7206.c
index c2268bd..b27a5e2 100644
--- a/arch/sh/kernel/cpu/sh2a/clock-sh7206.c
+++ b/arch/sh/kernel/cpu/sh2a/clock-sh7206.c
@@ -34,7 +34,7 @@
 
 static void master_clk_init(struct clk *clk)
 {
-	clk->rate *= PLL2 * pll1rate[(ctrl_inw(FREQCR) >> 8) & 0x0007];
+	clk->rate *= PLL2 * pll1rate[(__raw_readw(FREQCR) >> 8) & 0x0007];
 }
 
 static struct clk_ops sh7206_master_clk_ops = {
@@ -43,7 +43,7 @@
 
 static unsigned long module_clk_recalc(struct clk *clk)
 {
-	int idx = (ctrl_inw(FREQCR) & 0x0007);
+	int idx = (__raw_readw(FREQCR) & 0x0007);
 	return clk->parent->rate / pfc_divisors[idx];
 }
 
@@ -53,7 +53,7 @@
 
 static unsigned long bus_clk_recalc(struct clk *clk)
 {
-	return clk->parent->rate / pll1rate[(ctrl_inw(FREQCR) >> 8) & 0x0007];
+	return clk->parent->rate / pll1rate[(__raw_readw(FREQCR) >> 8) & 0x0007];
 }
 
 static struct clk_ops sh7206_bus_clk_ops = {
@@ -62,7 +62,7 @@
 
 static unsigned long cpu_clk_recalc(struct clk *clk)
 {
-	int idx = (ctrl_inw(FREQCR) & 0x0007);
+	int idx = (__raw_readw(FREQCR) & 0x0007);
 	return clk->parent->rate / ifc_divisors[idx];
 }
 
diff --git a/arch/sh/kernel/cpu/sh2a/fpu.c b/arch/sh/kernel/cpu/sh2a/fpu.c
index d395ce5..488d24e 100644
--- a/arch/sh/kernel/cpu/sh2a/fpu.c
+++ b/arch/sh/kernel/cpu/sh2a/fpu.c
@@ -26,8 +26,7 @@
 /*
  * Save FPU registers onto task structure.
  */
-void
-save_fpu(struct task_struct *tsk)
+void save_fpu(struct task_struct *tsk)
 {
 	unsigned long dummy;
 
@@ -52,7 +51,7 @@
 		     "fmov.s	fr0, @-%0\n\t"
 		     "lds	%3, fpscr\n\t"
 		     : "=r" (dummy)
-		     : "0" ((char *)(&tsk->thread.fpu.hard.status)),
+		     : "0" ((char *)(&tsk->thread.xstate->hardfpu.status)),
 		       "r" (FPSCR_RCHG),
 		       "r" (FPSCR_INIT)
 		     : "memory");
@@ -60,8 +59,7 @@
 	disable_fpu();
 }
 
-static void
-restore_fpu(struct task_struct *tsk)
+void restore_fpu(struct task_struct *tsk)
 {
 	unsigned long dummy;
 
@@ -85,45 +83,12 @@
 		     "lds.l	@%0+, fpscr\n\t"
 		     "lds.l	@%0+, fpul\n\t"
 		     : "=r" (dummy)
-		     : "0" (&tsk->thread.fpu), "r" (FPSCR_RCHG)
+		     : "0" (tsk->thread.xstate), "r" (FPSCR_RCHG)
 		     : "memory");
 	disable_fpu();
 }
 
 /*
- * Load the FPU with signalling NANS.  This bit pattern we're using
- * has the property that no matter wether considered as single or as
- * double precission represents signaling NANS.
- */
-
-static void
-fpu_init(void)
-{
-	enable_fpu();
-	asm volatile("lds	%0, fpul\n\t"
-		     "fsts	fpul, fr0\n\t"
-		     "fsts	fpul, fr1\n\t"
-		     "fsts	fpul, fr2\n\t"
-		     "fsts	fpul, fr3\n\t"
-		     "fsts	fpul, fr4\n\t"
-		     "fsts	fpul, fr5\n\t"
-		     "fsts	fpul, fr6\n\t"
-		     "fsts	fpul, fr7\n\t"
-		     "fsts	fpul, fr8\n\t"
-		     "fsts	fpul, fr9\n\t"
-		     "fsts	fpul, fr10\n\t"
-		     "fsts	fpul, fr11\n\t"
-		     "fsts	fpul, fr12\n\t"
-		     "fsts	fpul, fr13\n\t"
-		     "fsts	fpul, fr14\n\t"
-		     "fsts	fpul, fr15\n\t"
-		     "lds	%2, fpscr\n\t"
-		     : /* no output */
-		     : "r" (0), "r" (FPSCR_RCHG), "r" (FPSCR_INIT));
-	disable_fpu();
-}
-
-/*
  *	Emulate arithmetic ops on denormalized number for some FPU insns.
  */
 
@@ -490,9 +455,9 @@
 	if ((finsn & 0xf1ff) == 0xf0ad) { /* fcnvsd */
 		struct task_struct *tsk = current;
 
-		if ((tsk->thread.fpu.hard.fpscr & FPSCR_FPU_ERROR)) {
+		if ((tsk->thread.xstate->hardfpu.fpscr & FPSCR_FPU_ERROR)) {
 			/* FPU error */
-			denormal_to_double (&tsk->thread.fpu.hard,
+			denormal_to_double (&tsk->thread.xstate->hardfpu,
 					    (finsn >> 8) & 0xf);
 		} else
 			return 0;
@@ -507,9 +472,9 @@
 
 		n = (finsn >> 8) & 0xf;
 		m = (finsn >> 4) & 0xf;
-		hx = tsk->thread.fpu.hard.fp_regs[n];
-		hy = tsk->thread.fpu.hard.fp_regs[m];
-		fpscr = tsk->thread.fpu.hard.fpscr;
+		hx = tsk->thread.xstate->hardfpu.fp_regs[n];
+		hy = tsk->thread.xstate->hardfpu.fp_regs[m];
+		fpscr = tsk->thread.xstate->hardfpu.fpscr;
 		prec = fpscr & (1 << 19);
 
 		if ((fpscr & FPSCR_FPU_ERROR)
@@ -519,15 +484,15 @@
 
 			/* FPU error because of denormal */
 			llx = ((long long) hx << 32)
-			       | tsk->thread.fpu.hard.fp_regs[n+1];
+			       | tsk->thread.xstate->hardfpu.fp_regs[n+1];
 			lly = ((long long) hy << 32)
-			       | tsk->thread.fpu.hard.fp_regs[m+1];
+			       | tsk->thread.xstate->hardfpu.fp_regs[m+1];
 			if ((hx & 0x7fffffff) >= 0x00100000)
 				llx = denormal_muld(lly, llx);
 			else
 				llx = denormal_muld(llx, lly);
-			tsk->thread.fpu.hard.fp_regs[n] = llx >> 32;
-			tsk->thread.fpu.hard.fp_regs[n+1] = llx & 0xffffffff;
+			tsk->thread.xstate->hardfpu.fp_regs[n] = llx >> 32;
+			tsk->thread.xstate->hardfpu.fp_regs[n+1] = llx & 0xffffffff;
 		} else if ((fpscr & FPSCR_FPU_ERROR)
 		     && (!prec && ((hx & 0x7fffffff) < 0x00800000
 				   || (hy & 0x7fffffff) < 0x00800000))) {
@@ -536,7 +501,7 @@
 				hx = denormal_mulf(hy, hx);
 			else
 				hx = denormal_mulf(hx, hy);
-			tsk->thread.fpu.hard.fp_regs[n] = hx;
+			tsk->thread.xstate->hardfpu.fp_regs[n] = hx;
 		} else
 			return 0;
 
@@ -550,9 +515,9 @@
 
 		n = (finsn >> 8) & 0xf;
 		m = (finsn >> 4) & 0xf;
-		hx = tsk->thread.fpu.hard.fp_regs[n];
-		hy = tsk->thread.fpu.hard.fp_regs[m];
-		fpscr = tsk->thread.fpu.hard.fpscr;
+		hx = tsk->thread.xstate->hardfpu.fp_regs[n];
+		hy = tsk->thread.xstate->hardfpu.fp_regs[m];
+		fpscr = tsk->thread.xstate->hardfpu.fpscr;
 		prec = fpscr & (1 << 19);
 
 		if ((fpscr & FPSCR_FPU_ERROR)
@@ -562,15 +527,15 @@
 
 			/* FPU error because of denormal */
 			llx = ((long long) hx << 32)
-			       | tsk->thread.fpu.hard.fp_regs[n+1];
+			       | tsk->thread.xstate->hardfpu.fp_regs[n+1];
 			lly = ((long long) hy << 32)
-			       | tsk->thread.fpu.hard.fp_regs[m+1];
+			       | tsk->thread.xstate->hardfpu.fp_regs[m+1];
 			if ((finsn & 0xf00f) == 0xf000)
 				llx = denormal_addd(llx, lly);
 			else
 				llx = denormal_addd(llx, lly ^ (1LL << 63));
-			tsk->thread.fpu.hard.fp_regs[n] = llx >> 32;
-			tsk->thread.fpu.hard.fp_regs[n+1] = llx & 0xffffffff;
+			tsk->thread.xstate->hardfpu.fp_regs[n] = llx >> 32;
+			tsk->thread.xstate->hardfpu.fp_regs[n+1] = llx & 0xffffffff;
 		} else if ((fpscr & FPSCR_FPU_ERROR)
 		     && (!prec && ((hx & 0x7fffffff) < 0x00800000
 				   || (hy & 0x7fffffff) < 0x00800000))) {
@@ -579,7 +544,7 @@
 				hx = denormal_addf(hx, hy);
 			else
 				hx = denormal_addf(hx, hy ^ 0x80000000);
-			tsk->thread.fpu.hard.fp_regs[n] = hx;
+			tsk->thread.xstate->hardfpu.fp_regs[n] = hx;
 		} else
 			return 0;
 
@@ -597,7 +562,7 @@
 
 	__unlazy_fpu(tsk, regs);
 	if (ieee_fpe_handler(regs)) {
-		tsk->thread.fpu.hard.fpscr &=
+		tsk->thread.xstate->hardfpu.fpscr &=
 			~(FPSCR_CAUSE_MASK | FPSCR_FLAG_MASK);
 		grab_fpu(regs);
 		restore_fpu(tsk);
@@ -607,33 +572,3 @@
 
 	force_sig(SIGFPE, tsk);
 }
-
-void fpu_state_restore(struct pt_regs *regs)
-{
-	struct task_struct *tsk = current;
-
-	grab_fpu(regs);
-	if (unlikely(!user_mode(regs))) {
-		printk(KERN_ERR "BUG: FPU is used in kernel mode.\n");
-		BUG();
-		return;
-	}
-
-	if (likely(used_math())) {
-		/* Using the FPU again.  */
-		restore_fpu(tsk);
-	} else	{
-		/* First time FPU user.  */
-		fpu_init();
-		set_used_math();
-	}
-	task_thread_info(tsk)->status |= TS_USEDFPU;
-	tsk->fpu_counter++;
-}
-
-BUILD_TRAP_HANDLER(fpu_state_restore)
-{
-	TRAP_HANDLER_DECL;
-
-	fpu_state_restore(regs);
-}
diff --git a/arch/sh/kernel/cpu/sh3/clock-sh3.c b/arch/sh/kernel/cpu/sh3/clock-sh3.c
index 27b8738..b78384a 100644
--- a/arch/sh/kernel/cpu/sh3/clock-sh3.c
+++ b/arch/sh/kernel/cpu/sh3/clock-sh3.c
@@ -28,7 +28,7 @@
 
 static void master_clk_init(struct clk *clk)
 {
-	int frqcr = ctrl_inw(FRQCR);
+	int frqcr = __raw_readw(FRQCR);
 	int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003);
 
 	clk->rate *= pfc_divisors[idx];
@@ -40,7 +40,7 @@
 
 static unsigned long module_clk_recalc(struct clk *clk)
 {
-	int frqcr = ctrl_inw(FRQCR);
+	int frqcr = __raw_readw(FRQCR);
 	int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003);
 
 	return clk->parent->rate / pfc_divisors[idx];
@@ -52,7 +52,7 @@
 
 static unsigned long bus_clk_recalc(struct clk *clk)
 {
-	int frqcr = ctrl_inw(FRQCR);
+	int frqcr = __raw_readw(FRQCR);
 	int idx = ((frqcr & 0x8000) >> 13) | ((frqcr & 0x0030) >> 4);
 
 	return clk->parent->rate / stc_multipliers[idx];
@@ -64,7 +64,7 @@
 
 static unsigned long cpu_clk_recalc(struct clk *clk)
 {
-	int frqcr = ctrl_inw(FRQCR);
+	int frqcr = __raw_readw(FRQCR);
 	int idx = ((frqcr & 0x4000) >> 12) | ((frqcr & 0x000c) >> 2);
 
 	return clk->parent->rate / ifc_divisors[idx];
diff --git a/arch/sh/kernel/cpu/sh3/clock-sh7705.c b/arch/sh/kernel/cpu/sh3/clock-sh7705.c
index 0ca8f2c..0ecea14 100644
--- a/arch/sh/kernel/cpu/sh3/clock-sh7705.c
+++ b/arch/sh/kernel/cpu/sh3/clock-sh7705.c
@@ -32,7 +32,7 @@
 
 static void master_clk_init(struct clk *clk)
 {
-	clk->rate *= pfc_divisors[ctrl_inw(FRQCR) & 0x0003];
+	clk->rate *= pfc_divisors[__raw_readw(FRQCR) & 0x0003];
 }
 
 static struct clk_ops sh7705_master_clk_ops = {
@@ -41,7 +41,7 @@
 
 static unsigned long module_clk_recalc(struct clk *clk)
 {
-	int idx = ctrl_inw(FRQCR) & 0x0003;
+	int idx = __raw_readw(FRQCR) & 0x0003;
 	return clk->parent->rate / pfc_divisors[idx];
 }
 
@@ -51,7 +51,7 @@
 
 static unsigned long bus_clk_recalc(struct clk *clk)
 {
-	int idx = (ctrl_inw(FRQCR) & 0x0300) >> 8;
+	int idx = (__raw_readw(FRQCR) & 0x0300) >> 8;
 	return clk->parent->rate / stc_multipliers[idx];
 }
 
@@ -61,7 +61,7 @@
 
 static unsigned long cpu_clk_recalc(struct clk *clk)
 {
-	int idx = (ctrl_inw(FRQCR) & 0x0030) >> 4;
+	int idx = (__raw_readw(FRQCR) & 0x0030) >> 4;
 	return clk->parent->rate / ifc_divisors[idx];
 }
 
diff --git a/arch/sh/kernel/cpu/sh3/clock-sh7706.c b/arch/sh/kernel/cpu/sh3/clock-sh7706.c
index 4bf7887..6f9ff8b 100644
--- a/arch/sh/kernel/cpu/sh3/clock-sh7706.c
+++ b/arch/sh/kernel/cpu/sh3/clock-sh7706.c
@@ -24,7 +24,7 @@
 
 static void master_clk_init(struct clk *clk)
 {
-	int frqcr = ctrl_inw(FRQCR);
+	int frqcr = __raw_readw(FRQCR);
 	int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003);
 
 	clk->rate *= pfc_divisors[idx];
@@ -36,7 +36,7 @@
 
 static unsigned long module_clk_recalc(struct clk *clk)
 {
-	int frqcr = ctrl_inw(FRQCR);
+	int frqcr = __raw_readw(FRQCR);
 	int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003);
 
 	return clk->parent->rate / pfc_divisors[idx];
@@ -48,7 +48,7 @@
 
 static unsigned long bus_clk_recalc(struct clk *clk)
 {
-	int frqcr = ctrl_inw(FRQCR);
+	int frqcr = __raw_readw(FRQCR);
 	int idx = ((frqcr & 0x8000) >> 13) | ((frqcr & 0x0030) >> 4);
 
 	return clk->parent->rate / stc_multipliers[idx];
@@ -60,7 +60,7 @@
 
 static unsigned long cpu_clk_recalc(struct clk *clk)
 {
-	int frqcr = ctrl_inw(FRQCR);
+	int frqcr = __raw_readw(FRQCR);
 	int idx = ((frqcr & 0x4000) >> 12) | ((frqcr & 0x000c) >> 2);
 
 	return clk->parent->rate / ifc_divisors[idx];
diff --git a/arch/sh/kernel/cpu/sh3/clock-sh7709.c b/arch/sh/kernel/cpu/sh3/clock-sh7709.c
index e874950..f302ba0 100644
--- a/arch/sh/kernel/cpu/sh3/clock-sh7709.c
+++ b/arch/sh/kernel/cpu/sh3/clock-sh7709.c
@@ -24,7 +24,7 @@
 
 static void master_clk_init(struct clk *clk)
 {
-	int frqcr = ctrl_inw(FRQCR);
+	int frqcr = __raw_readw(FRQCR);
 	int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003);
 
 	clk->rate *= pfc_divisors[idx];
@@ -36,7 +36,7 @@
 
 static unsigned long module_clk_recalc(struct clk *clk)
 {
-	int frqcr = ctrl_inw(FRQCR);
+	int frqcr = __raw_readw(FRQCR);
 	int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003);
 
 	return clk->parent->rate / pfc_divisors[idx];
@@ -48,7 +48,7 @@
 
 static unsigned long bus_clk_recalc(struct clk *clk)
 {
-	int frqcr = ctrl_inw(FRQCR);
+	int frqcr = __raw_readw(FRQCR);
 	int idx = (frqcr & 0x0080) ?
 		((frqcr & 0x8000) >> 13) | ((frqcr & 0x0030) >> 4) : 1;
 
@@ -61,7 +61,7 @@
 
 static unsigned long cpu_clk_recalc(struct clk *clk)
 {
-	int frqcr = ctrl_inw(FRQCR);
+	int frqcr = __raw_readw(FRQCR);
 	int idx = ((frqcr & 0x4000) >> 12) | ((frqcr & 0x000c) >> 2);
 
 	return clk->parent->rate / ifc_divisors[idx];
diff --git a/arch/sh/kernel/cpu/sh3/clock-sh7710.c b/arch/sh/kernel/cpu/sh3/clock-sh7710.c
index 030a58b..29a87d8 100644
--- a/arch/sh/kernel/cpu/sh3/clock-sh7710.c
+++ b/arch/sh/kernel/cpu/sh3/clock-sh7710.c
@@ -26,7 +26,7 @@
 
 static void master_clk_init(struct clk *clk)
 {
-	clk->rate *= md_table[ctrl_inw(FRQCR) & 0x0007];
+	clk->rate *= md_table[__raw_readw(FRQCR) & 0x0007];
 }
 
 static struct clk_ops sh7710_master_clk_ops = {
@@ -35,7 +35,7 @@
 
 static unsigned long module_clk_recalc(struct clk *clk)
 {
-	int idx = (ctrl_inw(FRQCR) & 0x0007);
+	int idx = (__raw_readw(FRQCR) & 0x0007);
 	return clk->parent->rate / md_table[idx];
 }
 
@@ -45,7 +45,7 @@
 
 static unsigned long bus_clk_recalc(struct clk *clk)
 {
-	int idx = (ctrl_inw(FRQCR) & 0x0700) >> 8;
+	int idx = (__raw_readw(FRQCR) & 0x0700) >> 8;
 	return clk->parent->rate / md_table[idx];
 }
 
@@ -55,7 +55,7 @@
 
 static unsigned long cpu_clk_recalc(struct clk *clk)
 {
-	int idx = (ctrl_inw(FRQCR) & 0x0070) >> 4;
+	int idx = (__raw_readw(FRQCR) & 0x0070) >> 4;
 	return clk->parent->rate / md_table[idx];
 }
 
diff --git a/arch/sh/kernel/cpu/sh3/clock-sh7712.c b/arch/sh/kernel/cpu/sh3/clock-sh7712.c
index 6428ee6c..b0d0c52 100644
--- a/arch/sh/kernel/cpu/sh3/clock-sh7712.c
+++ b/arch/sh/kernel/cpu/sh3/clock-sh7712.c
@@ -23,7 +23,7 @@
 
 static void master_clk_init(struct clk *clk)
 {
-	int frqcr = ctrl_inw(FRQCR);
+	int frqcr = __raw_readw(FRQCR);
 	int idx = (frqcr & 0x0300) >> 8;
 
 	clk->rate *= multipliers[idx];
@@ -35,7 +35,7 @@
 
 static unsigned long module_clk_recalc(struct clk *clk)
 {
-	int frqcr = ctrl_inw(FRQCR);
+	int frqcr = __raw_readw(FRQCR);
 	int idx = frqcr & 0x0007;
 
 	return clk->parent->rate / divisors[idx];
@@ -47,7 +47,7 @@
 
 static unsigned long cpu_clk_recalc(struct clk *clk)
 {
-	int frqcr = ctrl_inw(FRQCR);
+	int frqcr = __raw_readw(FRQCR);
 	int idx = (frqcr & 0x0030) >> 4;
 
 	return clk->parent->rate / divisors[idx];
diff --git a/arch/sh/kernel/cpu/sh3/ex.S b/arch/sh/kernel/cpu/sh3/ex.S
index 46610c3..99b4d02 100644
--- a/arch/sh/kernel/cpu/sh3/ex.S
+++ b/arch/sh/kernel/cpu/sh3/ex.S
@@ -49,7 +49,7 @@
 	.long	exception_error	! reserved_instruction (filled by trap_init) /* 180 */
 	.long	exception_error	! illegal_slot_instruction (filled by trap_init) /*1A0*/
 	.long	nmi_trap_handler	/* 1C0 */	! Allow trap to debugger
-	.long	break_point_trap	/* 1E0 */
+	.long	breakpoint_trap_handler	/* 1E0 */
 
 	/*
 	 * Pad the remainder of the table out, exceptions residing in far
diff --git a/arch/sh/kernel/cpu/sh3/probe.c b/arch/sh/kernel/cpu/sh3/probe.c
index f9c7df6..295ec4c 100644
--- a/arch/sh/kernel/cpu/sh3/probe.c
+++ b/arch/sh/kernel/cpu/sh3/probe.c
@@ -16,7 +16,7 @@
 #include <asm/cache.h>
 #include <asm/io.h>
 
-int __uses_jump_to_uncached detect_cpu_and_cache_system(void)
+int detect_cpu_and_cache_system(void)
 {
 	unsigned long addr0, addr1, data0, data1, data2, data3;
 
@@ -30,23 +30,23 @@
 	addr1 = CACHE_OC_ADDRESS_ARRAY + (1 << 12);
 
 	/* First, write back & invalidate */
-	data0  = ctrl_inl(addr0);
-	ctrl_outl(data0&~(SH_CACHE_VALID|SH_CACHE_UPDATED), addr0);
-	data1  = ctrl_inl(addr1);
-	ctrl_outl(data1&~(SH_CACHE_VALID|SH_CACHE_UPDATED), addr1);
+	data0  = __raw_readl(addr0);
+	__raw_writel(data0&~(SH_CACHE_VALID|SH_CACHE_UPDATED), addr0);
+	data1  = __raw_readl(addr1);
+	__raw_writel(data1&~(SH_CACHE_VALID|SH_CACHE_UPDATED), addr1);
 
 	/* Next, check if there's shadow or not */
-	data0 = ctrl_inl(addr0);
+	data0 = __raw_readl(addr0);
 	data0 ^= SH_CACHE_VALID;
-	ctrl_outl(data0, addr0);
-	data1 = ctrl_inl(addr1);
+	__raw_writel(data0, addr0);
+	data1 = __raw_readl(addr1);
 	data2 = data1 ^ SH_CACHE_VALID;
-	ctrl_outl(data2, addr1);
-	data3 = ctrl_inl(addr0);
+	__raw_writel(data2, addr1);
+	data3 = __raw_readl(addr0);
 
 	/* Lastly, invaliate them. */
-	ctrl_outl(data0&~SH_CACHE_VALID, addr0);
-	ctrl_outl(data2&~SH_CACHE_VALID, addr1);
+	__raw_writel(data0&~SH_CACHE_VALID, addr0);
+	__raw_writel(data2&~SH_CACHE_VALID, addr1);
 
 	back_to_cached();
 
@@ -94,9 +94,9 @@
 		boot_cpu_data.dcache.way_incr	= (1 << 13);
 		boot_cpu_data.dcache.entry_mask	= 0x1ff0;
 		boot_cpu_data.dcache.sets	= 512;
-		ctrl_outl(CCR_CACHE_32KB, CCR3_REG);
+		__raw_writel(CCR_CACHE_32KB, CCR3_REG);
 #else
-		ctrl_outl(CCR_CACHE_16KB, CCR3_REG);
+		__raw_writel(CCR_CACHE_16KB, CCR3_REG);
 #endif
 #endif
 	}
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh3.c b/arch/sh/kernel/cpu/sh3/setup-sh3.c
index c988468..53be70b 100644
--- a/arch/sh/kernel/cpu/sh3/setup-sh3.c
+++ b/arch/sh/kernel/cpu/sh3/setup-sh3.c
@@ -58,7 +58,7 @@
 void __init plat_irq_setup_pins(int mode)
 {
 	if (mode == IRQ_MODE_IRQ) {
-		ctrl_outw(ctrl_inw(INTC_ICR1) & ~INTC_ICR1_IRQLVL, INTC_ICR1);
+		__raw_writew(__raw_readw(INTC_ICR1) & ~INTC_ICR1_IRQLVL, INTC_ICR1);
 		register_intc_controller(&intc_desc_irq0123);
 		return;
 	}
diff --git a/arch/sh/kernel/cpu/sh4/clock-sh4-202.c b/arch/sh/kernel/cpu/sh4/clock-sh4-202.c
index 21421e3..6b80850 100644
--- a/arch/sh/kernel/cpu/sh4/clock-sh4-202.c
+++ b/arch/sh/kernel/cpu/sh4/clock-sh4-202.c
@@ -23,7 +23,7 @@
 
 static unsigned long emi_clk_recalc(struct clk *clk)
 {
-	int idx = ctrl_inl(CPG2_FRQCR3) & 0x0007;
+	int idx = __raw_readl(CPG2_FRQCR3) & 0x0007;
 	return clk->parent->rate / frqcr3_divisors[idx];
 }
 
@@ -52,7 +52,7 @@
 
 static unsigned long femi_clk_recalc(struct clk *clk)
 {
-	int idx = (ctrl_inl(CPG2_FRQCR3) >> 3) & 0x0007;
+	int idx = (__raw_readl(CPG2_FRQCR3) >> 3) & 0x0007;
 	return clk->parent->rate / frqcr3_divisors[idx];
 }
 
@@ -92,7 +92,7 @@
 
 static unsigned long shoc_clk_recalc(struct clk *clk)
 {
-	int idx = (ctrl_inl(CPG2_FRQCR3) >> 6) & 0x0007;
+	int idx = (__raw_readl(CPG2_FRQCR3) >> 6) & 0x0007;
 	return clk->parent->rate / frqcr3_divisors[idx];
 }
 
@@ -122,10 +122,10 @@
 
 	tmp = frqcr3_lookup(clk, rate);
 
-	frqcr3 = ctrl_inl(CPG2_FRQCR3);
+	frqcr3 = __raw_readl(CPG2_FRQCR3);
 	frqcr3 &= ~(0x0007 << 6);
 	frqcr3 |= tmp << 6;
-	ctrl_outl(frqcr3, CPG2_FRQCR3);
+	__raw_writel(frqcr3, CPG2_FRQCR3);
 
 	clk->rate = clk->parent->rate / frqcr3_divisors[tmp];
 
diff --git a/arch/sh/kernel/cpu/sh4/clock-sh4.c b/arch/sh/kernel/cpu/sh4/clock-sh4.c
index 73294d9..5add75c 100644
--- a/arch/sh/kernel/cpu/sh4/clock-sh4.c
+++ b/arch/sh/kernel/cpu/sh4/clock-sh4.c
@@ -28,7 +28,7 @@
 
 static void master_clk_init(struct clk *clk)
 {
-	clk->rate *= pfc_divisors[ctrl_inw(FRQCR) & 0x0007];
+	clk->rate *= pfc_divisors[__raw_readw(FRQCR) & 0x0007];
 }
 
 static struct clk_ops sh4_master_clk_ops = {
@@ -37,7 +37,7 @@
 
 static unsigned long module_clk_recalc(struct clk *clk)
 {
-	int idx = (ctrl_inw(FRQCR) & 0x0007);
+	int idx = (__raw_readw(FRQCR) & 0x0007);
 	return clk->parent->rate / pfc_divisors[idx];
 }
 
@@ -47,7 +47,7 @@
 
 static unsigned long bus_clk_recalc(struct clk *clk)
 {
-	int idx = (ctrl_inw(FRQCR) >> 3) & 0x0007;
+	int idx = (__raw_readw(FRQCR) >> 3) & 0x0007;
 	return clk->parent->rate / bfc_divisors[idx];
 }
 
@@ -57,7 +57,7 @@
 
 static unsigned long cpu_clk_recalc(struct clk *clk)
 {
-	int idx = (ctrl_inw(FRQCR) >> 6) & 0x0007;
+	int idx = (__raw_readw(FRQCR) >> 6) & 0x0007;
 	return clk->parent->rate / ifc_divisors[idx];
 }
 
diff --git a/arch/sh/kernel/cpu/sh4/fpu.c b/arch/sh/kernel/cpu/sh4/fpu.c
index e97857a..447482d 100644
--- a/arch/sh/kernel/cpu/sh4/fpu.c
+++ b/arch/sh/kernel/cpu/sh4/fpu.c
@@ -85,14 +85,14 @@
 		      "fmov.s	fr1, @-%0\n\t"
 		      "fmov.s	fr0, @-%0\n\t"
 		      "lds	%3, fpscr\n\t":"=r" (dummy)
-		      :"0"((char *)(&tsk->thread.fpu.hard.status)),
+		      :"0"((char *)(&tsk->thread.xstate->hardfpu.status)),
 		      "r"(FPSCR_RCHG), "r"(FPSCR_INIT)
 		      :"memory");
 
 	disable_fpu();
 }
 
-static void restore_fpu(struct task_struct *tsk)
+void restore_fpu(struct task_struct *tsk)
 {
 	unsigned long dummy;
 
@@ -135,62 +135,11 @@
 		      "lds.l	@%0+, fpscr\n\t"
 		      "lds.l	@%0+, fpul\n\t"
 		      :"=r" (dummy)
-		      :"0"(&tsk->thread.fpu), "r"(FPSCR_RCHG)
+		      :"0" (tsk->thread.xstate), "r" (FPSCR_RCHG)
 		      :"memory");
 	disable_fpu();
 }
 
-/*
- * Load the FPU with signalling NANS.  This bit pattern we're using
- * has the property that no matter wether considered as single or as
- * double precision represents signaling NANS.
- */
-
-static void fpu_init(void)
-{
-	enable_fpu();
-	asm volatile (	"lds	%0, fpul\n\t"
-			"lds	%1, fpscr\n\t"
-			"fsts	fpul, fr0\n\t"
-			"fsts	fpul, fr1\n\t"
-			"fsts	fpul, fr2\n\t"
-			"fsts	fpul, fr3\n\t"
-			"fsts	fpul, fr4\n\t"
-			"fsts	fpul, fr5\n\t"
-			"fsts	fpul, fr6\n\t"
-			"fsts	fpul, fr7\n\t"
-			"fsts	fpul, fr8\n\t"
-			"fsts	fpul, fr9\n\t"
-			"fsts	fpul, fr10\n\t"
-			"fsts	fpul, fr11\n\t"
-			"fsts	fpul, fr12\n\t"
-			"fsts	fpul, fr13\n\t"
-			"fsts	fpul, fr14\n\t"
-			"fsts	fpul, fr15\n\t"
-			"frchg\n\t"
-			"fsts	fpul, fr0\n\t"
-			"fsts	fpul, fr1\n\t"
-			"fsts	fpul, fr2\n\t"
-			"fsts	fpul, fr3\n\t"
-			"fsts	fpul, fr4\n\t"
-			"fsts	fpul, fr5\n\t"
-			"fsts	fpul, fr6\n\t"
-			"fsts	fpul, fr7\n\t"
-			"fsts	fpul, fr8\n\t"
-			"fsts	fpul, fr9\n\t"
-			"fsts	fpul, fr10\n\t"
-			"fsts	fpul, fr11\n\t"
-			"fsts	fpul, fr12\n\t"
-			"fsts	fpul, fr13\n\t"
-			"fsts	fpul, fr14\n\t"
-			"fsts	fpul, fr15\n\t"
-			"frchg\n\t"
-			"lds	%2, fpscr\n\t"
-			:	/* no output */
-			:"r" (0), "r"(FPSCR_RCHG), "r"(FPSCR_INIT));
-	disable_fpu();
-}
-
 /**
  *      denormal_to_double - Given denormalized float number,
  *                           store double float
@@ -282,9 +231,9 @@
 		/* fcnvsd */
 		struct task_struct *tsk = current;
 
-		if ((tsk->thread.fpu.hard.fpscr & FPSCR_CAUSE_ERROR))
+		if ((tsk->thread.xstate->hardfpu.fpscr & FPSCR_CAUSE_ERROR))
 			/* FPU error */
-			denormal_to_double(&tsk->thread.fpu.hard,
+			denormal_to_double(&tsk->thread.xstate->hardfpu,
 					   (finsn >> 8) & 0xf);
 		else
 			return 0;
@@ -300,9 +249,9 @@
 
 		n = (finsn >> 8) & 0xf;
 		m = (finsn >> 4) & 0xf;
-		hx = tsk->thread.fpu.hard.fp_regs[n];
-		hy = tsk->thread.fpu.hard.fp_regs[m];
-		fpscr = tsk->thread.fpu.hard.fpscr;
+		hx = tsk->thread.xstate->hardfpu.fp_regs[n];
+		hy = tsk->thread.xstate->hardfpu.fp_regs[m];
+		fpscr = tsk->thread.xstate->hardfpu.fpscr;
 		prec = fpscr & FPSCR_DBL_PRECISION;
 
 		if ((fpscr & FPSCR_CAUSE_ERROR)
@@ -312,18 +261,18 @@
 
 			/* FPU error because of denormal (doubles) */
 			llx = ((long long)hx << 32)
-			    | tsk->thread.fpu.hard.fp_regs[n + 1];
+			    | tsk->thread.xstate->hardfpu.fp_regs[n + 1];
 			lly = ((long long)hy << 32)
-			    | tsk->thread.fpu.hard.fp_regs[m + 1];
+			    | tsk->thread.xstate->hardfpu.fp_regs[m + 1];
 			llx = float64_mul(llx, lly);
-			tsk->thread.fpu.hard.fp_regs[n] = llx >> 32;
-			tsk->thread.fpu.hard.fp_regs[n + 1] = llx & 0xffffffff;
+			tsk->thread.xstate->hardfpu.fp_regs[n] = llx >> 32;
+			tsk->thread.xstate->hardfpu.fp_regs[n + 1] = llx & 0xffffffff;
 		} else if ((fpscr & FPSCR_CAUSE_ERROR)
 			   && (!prec && ((hx & 0x7fffffff) < 0x00800000
 					 || (hy & 0x7fffffff) < 0x00800000))) {
 			/* FPU error because of denormal (floats) */
 			hx = float32_mul(hx, hy);
-			tsk->thread.fpu.hard.fp_regs[n] = hx;
+			tsk->thread.xstate->hardfpu.fp_regs[n] = hx;
 		} else
 			return 0;
 
@@ -338,9 +287,9 @@
 
 		n = (finsn >> 8) & 0xf;
 		m = (finsn >> 4) & 0xf;
-		hx = tsk->thread.fpu.hard.fp_regs[n];
-		hy = tsk->thread.fpu.hard.fp_regs[m];
-		fpscr = tsk->thread.fpu.hard.fpscr;
+		hx = tsk->thread.xstate->hardfpu.fp_regs[n];
+		hy = tsk->thread.xstate->hardfpu.fp_regs[m];
+		fpscr = tsk->thread.xstate->hardfpu.fpscr;
 		prec = fpscr & FPSCR_DBL_PRECISION;
 
 		if ((fpscr & FPSCR_CAUSE_ERROR)
@@ -350,15 +299,15 @@
 
 			/* FPU error because of denormal (doubles) */
 			llx = ((long long)hx << 32)
-			    | tsk->thread.fpu.hard.fp_regs[n + 1];
+			    | tsk->thread.xstate->hardfpu.fp_regs[n + 1];
 			lly = ((long long)hy << 32)
-			    | tsk->thread.fpu.hard.fp_regs[m + 1];
+			    | tsk->thread.xstate->hardfpu.fp_regs[m + 1];
 			if ((finsn & 0xf00f) == 0xf000)
 				llx = float64_add(llx, lly);
 			else
 				llx = float64_sub(llx, lly);
-			tsk->thread.fpu.hard.fp_regs[n] = llx >> 32;
-			tsk->thread.fpu.hard.fp_regs[n + 1] = llx & 0xffffffff;
+			tsk->thread.xstate->hardfpu.fp_regs[n] = llx >> 32;
+			tsk->thread.xstate->hardfpu.fp_regs[n + 1] = llx & 0xffffffff;
 		} else if ((fpscr & FPSCR_CAUSE_ERROR)
 			   && (!prec && ((hx & 0x7fffffff) < 0x00800000
 					 || (hy & 0x7fffffff) < 0x00800000))) {
@@ -367,7 +316,7 @@
 				hx = float32_add(hx, hy);
 			else
 				hx = float32_sub(hx, hy);
-			tsk->thread.fpu.hard.fp_regs[n] = hx;
+			tsk->thread.xstate->hardfpu.fp_regs[n] = hx;
 		} else
 			return 0;
 
@@ -382,9 +331,9 @@
 
 		n = (finsn >> 8) & 0xf;
 		m = (finsn >> 4) & 0xf;
-		hx = tsk->thread.fpu.hard.fp_regs[n];
-		hy = tsk->thread.fpu.hard.fp_regs[m];
-		fpscr = tsk->thread.fpu.hard.fpscr;
+		hx = tsk->thread.xstate->hardfpu.fp_regs[n];
+		hy = tsk->thread.xstate->hardfpu.fp_regs[m];
+		fpscr = tsk->thread.xstate->hardfpu.fpscr;
 		prec = fpscr & FPSCR_DBL_PRECISION;
 
 		if ((fpscr & FPSCR_CAUSE_ERROR)
@@ -394,20 +343,20 @@
 
 			/* FPU error because of denormal (doubles) */
 			llx = ((long long)hx << 32)
-			    | tsk->thread.fpu.hard.fp_regs[n + 1];
+			    | tsk->thread.xstate->hardfpu.fp_regs[n + 1];
 			lly = ((long long)hy << 32)
-			    | tsk->thread.fpu.hard.fp_regs[m + 1];
+			    | tsk->thread.xstate->hardfpu.fp_regs[m + 1];
 
 			llx = float64_div(llx, lly);
 
-			tsk->thread.fpu.hard.fp_regs[n] = llx >> 32;
-			tsk->thread.fpu.hard.fp_regs[n + 1] = llx & 0xffffffff;
+			tsk->thread.xstate->hardfpu.fp_regs[n] = llx >> 32;
+			tsk->thread.xstate->hardfpu.fp_regs[n + 1] = llx & 0xffffffff;
 		} else if ((fpscr & FPSCR_CAUSE_ERROR)
 			   && (!prec && ((hx & 0x7fffffff) < 0x00800000
 					 || (hy & 0x7fffffff) < 0x00800000))) {
 			/* FPU error because of denormal (floats) */
 			hx = float32_div(hx, hy);
-			tsk->thread.fpu.hard.fp_regs[n] = hx;
+			tsk->thread.xstate->hardfpu.fp_regs[n] = hx;
 		} else
 			return 0;
 
@@ -420,17 +369,17 @@
 		unsigned int hx;
 
 		m = (finsn >> 8) & 0x7;
-		hx = tsk->thread.fpu.hard.fp_regs[m];
+		hx = tsk->thread.xstate->hardfpu.fp_regs[m];
 
-		if ((tsk->thread.fpu.hard.fpscr & FPSCR_CAUSE_ERROR)
+		if ((tsk->thread.xstate->hardfpu.fpscr & FPSCR_CAUSE_ERROR)
 			&& ((hx & 0x7fffffff) < 0x00100000)) {
 			/* subnormal double to float conversion */
 			long long llx;
 
-			llx = ((long long)tsk->thread.fpu.hard.fp_regs[m] << 32)
-			    | tsk->thread.fpu.hard.fp_regs[m + 1];
+			llx = ((long long)tsk->thread.xstate->hardfpu.fp_regs[m] << 32)
+			    | tsk->thread.xstate->hardfpu.fp_regs[m + 1];
 
-			tsk->thread.fpu.hard.fpul = float64_to_float32(llx);
+			tsk->thread.xstate->hardfpu.fpul = float64_to_float32(llx);
 		} else
 			return 0;
 
@@ -449,7 +398,7 @@
 int float_rounding_mode(void)
 {
 	struct task_struct *tsk = current;
-	int roundingMode = FPSCR_ROUNDING_MODE(tsk->thread.fpu.hard.fpscr);
+	int roundingMode = FPSCR_ROUNDING_MODE(tsk->thread.xstate->hardfpu.fpscr);
 	return roundingMode;
 }
 
@@ -461,16 +410,16 @@
 	__unlazy_fpu(tsk, regs);
 	fpu_exception_flags = 0;
 	if (ieee_fpe_handler(regs)) {
-		tsk->thread.fpu.hard.fpscr &=
+		tsk->thread.xstate->hardfpu.fpscr &=
 		    ~(FPSCR_CAUSE_MASK | FPSCR_FLAG_MASK);
-		tsk->thread.fpu.hard.fpscr |= fpu_exception_flags;
+		tsk->thread.xstate->hardfpu.fpscr |= fpu_exception_flags;
 		/* Set the FPSCR flag as well as cause bits - simply
 		 * replicate the cause */
-		tsk->thread.fpu.hard.fpscr |= (fpu_exception_flags >> 10);
+		tsk->thread.xstate->hardfpu.fpscr |= (fpu_exception_flags >> 10);
 		grab_fpu(regs);
 		restore_fpu(tsk);
 		task_thread_info(tsk)->status |= TS_USEDFPU;
-		if ((((tsk->thread.fpu.hard.fpscr & FPSCR_ENABLE_MASK) >> 7) &
+		if ((((tsk->thread.xstate->hardfpu.fpscr & FPSCR_ENABLE_MASK) >> 7) &
 		     (fpu_exception_flags >> 2)) == 0) {
 			return;
 		}
@@ -478,33 +427,3 @@
 
 	force_sig(SIGFPE, tsk);
 }
-
-void fpu_state_restore(struct pt_regs *regs)
-{
-	struct task_struct *tsk = current;
-
-	grab_fpu(regs);
-	if (unlikely(!user_mode(regs))) {
-		printk(KERN_ERR "BUG: FPU is used in kernel mode.\n");
-		BUG();
-		return;
-	}
-
-	if (likely(used_math())) {
-		/* Using the FPU again.  */
-		restore_fpu(tsk);
-	} else {
-		/* First time FPU user.  */
-		fpu_init();
-		set_used_math();
-	}
-	task_thread_info(tsk)->status |= TS_USEDFPU;
-	tsk->fpu_counter++;
-}
-
-BUILD_TRAP_HANDLER(fpu_state_restore)
-{
-	TRAP_HANDLER_DECL;
-
-	fpu_state_restore(regs);
-}
diff --git a/arch/sh/kernel/cpu/sh4/probe.c b/arch/sh/kernel/cpu/sh4/probe.c
index d36f0c4..822977a 100644
--- a/arch/sh/kernel/cpu/sh4/probe.c
+++ b/arch/sh/kernel/cpu/sh4/probe.c
@@ -28,9 +28,9 @@
 		[9] = (1 << 16)
 	};
 
-	pvr = (ctrl_inl(CCN_PVR) >> 8) & 0xffffff;
-	prr = (ctrl_inl(CCN_PRR) >> 4) & 0xff;
-	cvr = (ctrl_inl(CCN_CVR));
+	pvr = (__raw_readl(CCN_PVR) >> 8) & 0xffffff;
+	prr = (__raw_readl(CCN_PRR) >> 4) & 0xff;
+	cvr = (__raw_readl(CCN_CVR));
 
 	/*
 	 * Setup some sane SH-4 defaults for the icache
@@ -71,11 +71,11 @@
 		boot_cpu_data.dcache.ways = 4;
 	} else {
 		/* And some SH-4 defaults.. */
-		boot_cpu_data.flags |= CPU_HAS_PTEA;
+		boot_cpu_data.flags |= CPU_HAS_PTEA | CPU_HAS_FPU;
 		boot_cpu_data.family = CPU_FAMILY_SH4;
 	}
 
-	/* FPU detection works for everyone */
+	/* FPU detection works for almost everyone */
 	if ((cvr & 0x20000000))
 		boot_cpu_data.flags |= CPU_HAS_FPU;
 
@@ -124,6 +124,7 @@
 		boot_cpu_data.type = CPU_SH7785;
 		break;
 	case 0x4004:
+	case 0x4005:
 		boot_cpu_data.type = CPU_SH7786;
 		boot_cpu_data.flags |= CPU_HAS_PTEAEX | CPU_HAS_L2_CACHE;
 		break;
@@ -160,6 +161,7 @@
 		break;
 	case 0x700:
 		boot_cpu_data.type = CPU_SH4_501;
+		boot_cpu_data.flags &= ~CPU_HAS_FPU;
 		boot_cpu_data.icache.ways = 2;
 		boot_cpu_data.dcache.ways = 2;
 		break;
@@ -227,7 +229,7 @@
 			 * Size calculation is much more sensible
 			 * than it is for the L1.
 			 *
-			 * Sizes are 128KB, 258KB, 512KB, and 1MB.
+			 * Sizes are 128KB, 256KB, 512KB, and 1MB.
 			 */
 			size = (cvr & 0xf) << 17;
 
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh4-202.c b/arch/sh/kernel/cpu/sh4/setup-sh4-202.c
index 4b73371..b9b7e10 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh4-202.c
+++ b/arch/sh/kernel/cpu/sh4/setup-sh4-202.c
@@ -198,7 +198,7 @@
 {
 	switch (mode) {
 	case IRQ_MODE_IRQ: /* individual interrupt mode for IRL3-0 */
-		ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR);
+		__raw_writew(__raw_readw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR);
 		register_intc_controller(&intc_desc_irlm);
 		break;
 	default:
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7750.c b/arch/sh/kernel/cpu/sh4/setup-sh7750.c
index b2a9df1..ffd79e5 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh7750.c
+++ b/arch/sh/kernel/cpu/sh4/setup-sh7750.c
@@ -442,7 +442,7 @@
 
 	switch (mode) {
 	case IRQ_MODE_IRQ: /* individual interrupt mode for IRL3-0 */
-		ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR);
+		__raw_writew(__raw_readw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR);
 		register_intc_controller(&intc_desc_irlm);
 		break;
 	default:
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7760.c b/arch/sh/kernel/cpu/sh4/setup-sh7760.c
index 5b74cc0..a16eb36 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh7760.c
+++ b/arch/sh/kernel/cpu/sh4/setup-sh7760.c
@@ -319,7 +319,7 @@
 {
 	switch (mode) {
 	case IRQ_MODE_IRQ:
-		ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR);
+		__raw_writew(__raw_readw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR);
 		register_intc_controller(&intc_desc_irq);
 		break;
 	default:
diff --git a/arch/sh/kernel/cpu/sh4/sq.c b/arch/sh/kernel/cpu/sh4/sq.c
index 8a8a993..fc065f9 100644
--- a/arch/sh/kernel/cpu/sh4/sq.c
+++ b/arch/sh/kernel/cpu/sh4/sq.c
@@ -43,9 +43,9 @@
 
 #define store_queue_barrier()			\
 do {						\
-	(void)ctrl_inl(P4SEG_STORE_QUE);	\
-	ctrl_outl(0, P4SEG_STORE_QUE + 0);	\
-	ctrl_outl(0, P4SEG_STORE_QUE + 8);	\
+	(void)__raw_readl(P4SEG_STORE_QUE);	\
+	__raw_writel(0, P4SEG_STORE_QUE + 0);	\
+	__raw_writel(0, P4SEG_STORE_QUE + 8);	\
 } while (0);
 
 /**
@@ -100,7 +100,7 @@
 	spin_unlock_irq(&sq_mapping_lock);
 }
 
-static int __sq_remap(struct sq_mapping *map, unsigned long flags)
+static int __sq_remap(struct sq_mapping *map, pgprot_t prot)
 {
 #if defined(CONFIG_MMU)
 	struct vm_struct *vma;
@@ -113,7 +113,7 @@
 
 	if (ioremap_page_range((unsigned long)vma->addr,
 			       (unsigned long)vma->addr + map->size,
-			       vma->phys_addr, __pgprot(flags))) {
+			       vma->phys_addr, prot)) {
 		vunmap(vma->addr);
 		return -EAGAIN;
 	}
@@ -123,8 +123,8 @@
 	 * straightforward, as we can just load up each queue's QACR with
 	 * the physical address appropriately masked.
 	 */
-	ctrl_outl(((map->addr >> 26) << 2) & 0x1c, SQ_QACR0);
-	ctrl_outl(((map->addr >> 26) << 2) & 0x1c, SQ_QACR1);
+	__raw_writel(((map->addr >> 26) << 2) & 0x1c, SQ_QACR0);
+	__raw_writel(((map->addr >> 26) << 2) & 0x1c, SQ_QACR1);
 #endif
 
 	return 0;
@@ -135,14 +135,14 @@
  * @phys: Physical address of mapping.
  * @size: Length of mapping.
  * @name: User invoking mapping.
- * @flags: Protection flags.
+ * @prot: Protection bits.
  *
  * Remaps the physical address @phys through the next available store queue
  * address of @size length. @name is logged at boot time as well as through
  * the sysfs interface.
  */
 unsigned long sq_remap(unsigned long phys, unsigned int size,
-		       const char *name, unsigned long flags)
+		       const char *name, pgprot_t prot)
 {
 	struct sq_mapping *map;
 	unsigned long end;
@@ -177,7 +177,7 @@
 
 	map->sq_addr = P4SEG_STORE_QUE + (page << PAGE_SHIFT);
 
-	ret = __sq_remap(map, pgprot_val(PAGE_KERNEL_NOCACHE) | flags);
+	ret = __sq_remap(map, prot);
 	if (unlikely(ret != 0))
 		goto out;
 
@@ -309,8 +309,7 @@
 		return -EIO;
 
 	if (likely(len)) {
-		int ret = sq_remap(base, len, "Userspace",
-				   pgprot_val(PAGE_SHARED));
+		int ret = sq_remap(base, len, "Userspace", PAGE_SHARED);
 		if (ret < 0)
 			return ret;
 	} else
diff --git a/arch/sh/kernel/cpu/sh4a/Makefile b/arch/sh/kernel/cpu/sh4a/Makefile
index 33bab47..b144e8a 100644
--- a/arch/sh/kernel/cpu/sh4a/Makefile
+++ b/arch/sh/kernel/cpu/sh4a/Makefile
@@ -41,7 +41,8 @@
 pinmux-$(CONFIG_CPU_SUBTYPE_SH7785)	:= pinmux-sh7785.o
 pinmux-$(CONFIG_CPU_SUBTYPE_SH7786)	:= pinmux-sh7786.o
 
-obj-y				+= $(clock-y)
-obj-$(CONFIG_SMP)		+= $(smp-y)
-obj-$(CONFIG_GENERIC_GPIO)	+= $(pinmux-y)
-obj-$(CONFIG_PERF_EVENTS)	+= perf_event.o
+obj-y					+= $(clock-y)
+obj-$(CONFIG_SMP)			+= $(smp-y)
+obj-$(CONFIG_GENERIC_GPIO)		+= $(pinmux-y)
+obj-$(CONFIG_PERF_EVENTS)		+= perf_event.o
+obj-$(CONFIG_HAVE_HW_BREAKPOINT)	+= ubc.o
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7343.c b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c
index 0ee3ee8..2c16df3 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7343.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c
@@ -107,13 +107,17 @@
 static int multipliers[] = { 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
 static int divisors[] = { 1, 3, 2, 5, 3, 4, 5, 6, 8, 10, 12, 16, 20 };
 
-static struct clk_div_mult_table div4_table = {
+static struct clk_div_mult_table div4_div_mult_table = {
 	.divisors = divisors,
 	.nr_divisors = ARRAY_SIZE(divisors),
 	.multipliers = multipliers,
 	.nr_multipliers = ARRAY_SIZE(multipliers),
 };
 
+static struct clk_div4_table div4_table = {
+	.div_mult_table = &div4_div_mult_table,
+};
+
 enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_B3, DIV4_P,
        DIV4_SIUA, DIV4_SIUB, DIV4_NR };
 
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7366.c b/arch/sh/kernel/cpu/sh4a/clock-sh7366.c
index a95ebab..91588d2 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7366.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7366.c
@@ -110,13 +110,17 @@
 static int multipliers[] = { 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
 static int divisors[] = { 1, 3, 2, 5, 3, 4, 5, 6, 8, 10, 12, 16, 20 };
 
-static struct clk_div_mult_table div4_table = {
+static struct clk_div_mult_table div4_div_mult_table = {
 	.divisors = divisors,
 	.nr_divisors = ARRAY_SIZE(divisors),
 	.multipliers = multipliers,
 	.nr_multipliers = ARRAY_SIZE(multipliers),
 };
 
+static struct clk_div4_table div4_table = {
+	.div_mult_table = &div4_div_mult_table,
+};
+
 enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_B3, DIV4_P,
        DIV4_SIUA, DIV4_SIUB, DIV4_NR };
 
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
index ea38b55..15db6d5 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
@@ -110,19 +110,22 @@
 static int multipliers[] = { 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
 static int divisors[] = { 1, 3, 2, 5, 3, 4, 5, 6, 8, 10, 12, 16, 20 };
 
-static struct clk_div_mult_table div4_table = {
+static struct clk_div_mult_table div4_div_mult_table = {
 	.divisors = divisors,
 	.nr_divisors = ARRAY_SIZE(divisors),
 	.multipliers = multipliers,
 	.nr_multipliers = ARRAY_SIZE(multipliers),
 };
 
-enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_B3, DIV4_P,
-       DIV4_SIUA, DIV4_SIUB, DIV4_IRDA, DIV4_NR };
+static struct clk_div4_table div4_table = {
+	.div_mult_table = &div4_div_mult_table,
+};
 
 #define DIV4(_str, _reg, _bit, _mask, _flags) \
   SH_CLK_DIV4(_str, &pll_clk, _reg, _bit, _mask, _flags)
 
+enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_B3, DIV4_P, DIV4_NR };
+
 struct clk div4_clks[DIV4_NR] = {
 	[DIV4_I] = DIV4("cpu_clk", FRQCR, 20, 0x1fef, CLK_ENABLE_ON_INIT),
 	[DIV4_U] = DIV4("umem_clk", FRQCR, 16, 0x1fff, CLK_ENABLE_ON_INIT),
@@ -130,9 +133,19 @@
 	[DIV4_B] = DIV4("bus_clk", FRQCR, 8, 0x1fff, CLK_ENABLE_ON_INIT),
 	[DIV4_B3] = DIV4("b3_clk", FRQCR, 4, 0x1fff, CLK_ENABLE_ON_INIT),
 	[DIV4_P] = DIV4("peripheral_clk", FRQCR, 0, 0x1fff, 0),
+};
+
+enum { DIV4_IRDA, DIV4_ENABLE_NR };
+
+struct clk div4_enable_clks[DIV4_ENABLE_NR] = {
+	[DIV4_IRDA] = DIV4("irda_clk", IRDACLKCR, 0, 0x1fff, 0),
+};
+
+enum { DIV4_SIUA, DIV4_SIUB, DIV4_REPARENT_NR };
+
+struct clk div4_reparent_clks[DIV4_REPARENT_NR] = {
 	[DIV4_SIUA] = DIV4("siua_clk", SCLKACR, 0, 0x1fff, 0),
 	[DIV4_SIUB] = DIV4("siub_clk", SCLKBCR, 0, 0x1fff, 0),
-	[DIV4_IRDA] = DIV4("irda_clk", IRDACLKCR, 0, 0x1fff, 0),
 };
 
 struct clk div6_clks[] = {
@@ -189,6 +202,14 @@
 		ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
 
 	if (!ret)
+		ret = sh_clk_div4_enable_register(div4_enable_clks,
+					DIV4_ENABLE_NR, &div4_table);
+
+	if (!ret)
+		ret = sh_clk_div4_reparent_register(div4_reparent_clks,
+					DIV4_REPARENT_NR, &div4_table);
+
+	if (!ret)
 		ret = sh_clk_div6_register(div6_clks, ARRAY_SIZE(div6_clks));
 
 	if (!ret)
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c
index 20a31c2..50babe0 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c
@@ -110,15 +110,18 @@
 static int multipliers[] = { 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
 static int divisors[] = { 1, 3, 2, 5, 3, 4, 5, 6, 8, 10, 12, 16, 20 };
 
-static struct clk_div_mult_table div4_table = {
+static struct clk_div_mult_table div4_div_mult_table = {
 	.divisors = divisors,
 	.nr_divisors = ARRAY_SIZE(divisors),
 	.multipliers = multipliers,
 	.nr_multipliers = ARRAY_SIZE(multipliers),
 };
 
-enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_B3, DIV4_P,
-       DIV4_SIUA, DIV4_SIUB, DIV4_IRDA, DIV4_NR };
+static struct clk_div4_table div4_table = {
+	.div_mult_table = &div4_div_mult_table,
+};
+
+enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_B3, DIV4_P, DIV4_NR };
 
 #define DIV4(_str, _reg, _bit, _mask, _flags) \
   SH_CLK_DIV4(_str, &pll_clk, _reg, _bit, _mask, _flags)
@@ -130,11 +133,20 @@
 	[DIV4_B] = DIV4("bus_clk", FRQCR, 8, 0x0dbf, CLK_ENABLE_ON_INIT),
 	[DIV4_B3] = DIV4("b3_clk", FRQCR, 4, 0x0db4, CLK_ENABLE_ON_INIT),
 	[DIV4_P] = DIV4("peripheral_clk", FRQCR, 0, 0x0dbf, 0),
-	[DIV4_SIUA] = DIV4("siua_clk", SCLKACR, 0, 0x0dbf, 0),
-	[DIV4_SIUB] = DIV4("siub_clk", SCLKBCR, 0, 0x0dbf, 0),
+};
+
+enum { DIV4_IRDA, DIV4_ENABLE_NR };
+
+struct clk div4_enable_clks[DIV4_ENABLE_NR] = {
 	[DIV4_IRDA] = DIV4("irda_clk", IRDACLKCR, 0, 0x0dbf, 0),
 };
 
+enum { DIV4_SIUA, DIV4_SIUB, DIV4_REPARENT_NR };
+
+struct clk div4_reparent_clks[DIV4_REPARENT_NR] = {
+	[DIV4_SIUA] = DIV4("siua_clk", SCLKACR, 0, 0x0dbf, 0),
+	[DIV4_SIUB] = DIV4("siub_clk", SCLKBCR, 0, 0x0dbf, 0),
+};
 struct clk div6_clks[] = {
 	SH_CLK_DIV6("video_clk", &pll_clk, VCLKCR, 0),
 };
@@ -216,6 +228,14 @@
 		ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
 
 	if (!ret)
+		ret = sh_clk_div4_enable_register(div4_enable_clks,
+					DIV4_ENABLE_NR, &div4_table);
+
+	if (!ret)
+		ret = sh_clk_div4_reparent_register(div4_reparent_clks,
+					DIV4_REPARENT_NR, &div4_table);
+
+	if (!ret)
 		ret = sh_clk_div6_register(div6_clks, ARRAY_SIZE(div6_clks));
 
 	if (!ret)
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c
index 9db7438..6707061 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c
@@ -127,13 +127,28 @@
 	&div3_clk,
 };
 
+static void div4_kick(struct clk *clk)
+{
+	unsigned long value;
+
+	/* set KICK bit in FRQCRA to update hardware setting */
+	value = __raw_readl(FRQCRA);
+	value |= (1 << 31);
+	__raw_writel(value, FRQCRA);
+}
+
 static int divisors[] = { 2, 3, 4, 6, 8, 12, 16, 0, 24, 32, 36, 48, 0, 72 };
 
-static struct clk_div_mult_table div4_table = {
+static struct clk_div_mult_table div4_div_mult_table = {
 	.divisors = divisors,
 	.nr_divisors = ARRAY_SIZE(divisors),
 };
 
+static struct clk_div4_table div4_table = {
+	.div_mult_table = &div4_div_mult_table,
+	.kick = div4_kick,
+};
+
 enum { DIV4_I, DIV4_SH, DIV4_B, DIV4_P, DIV4_M1, DIV4_NR };
 
 #define DIV4(_str, _reg, _bit, _mask, _flags) \
@@ -144,7 +159,7 @@
 	[DIV4_SH] = DIV4("shyway_clk", FRQCRA, 12, 0x2f7c, CLK_ENABLE_ON_INIT),
 	[DIV4_B] = DIV4("bus_clk", FRQCRA, 8, 0x2f7c, CLK_ENABLE_ON_INIT),
 	[DIV4_P] = DIV4("peripheral_clk", FRQCRA, 0, 0x2f7c, 0),
-	[DIV4_M1] = DIV4("vpu_clk", FRQCRB, 4, 0x2f7c, 0),
+	[DIV4_M1] = DIV4("vpu_clk", FRQCRB, 4, 0x2f7c, CLK_ENABLE_ON_INIT),
 };
 
 struct clk div6_clks[] = {
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7757.c b/arch/sh/kernel/cpu/sh4a/clock-sh7757.c
index ddc235c..86aae60 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7757.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7757.c
@@ -35,7 +35,7 @@
 
 static void module_clk_recalc(struct clk *clk)
 {
-	int idx = ctrl_inl(FRQCR) & 0x0000000f;
+	int idx = __raw_readl(FRQCR) & 0x0000000f;
 	clk->rate = clk->parent->rate / p1fc_divisors[idx];
 }
 
@@ -45,7 +45,7 @@
 
 static void bus_clk_recalc(struct clk *clk)
 {
-	int idx = (ctrl_inl(FRQCR) >> 8) & 0x0000000f;
+	int idx = (__raw_readl(FRQCR) >> 8) & 0x0000000f;
 	clk->rate = clk->parent->rate / bfc_divisors[idx];
 }
 
@@ -55,7 +55,7 @@
 
 static void cpu_clk_recalc(struct clk *clk)
 {
-	int idx = (ctrl_inl(FRQCR) >> 20) & 0x0000000f;
+	int idx = (__raw_readl(FRQCR) >> 20) & 0x0000000f;
 	clk->rate = clk->parent->rate / ifc_divisors[idx];
 }
 
@@ -78,7 +78,7 @@
 
 static void shyway_clk_recalc(struct clk *clk)
 {
-	int idx = (ctrl_inl(FRQCR) >> 12) & 0x0000000f;
+	int idx = (__raw_readl(FRQCR) >> 12) & 0x0000000f;
 	clk->rate = clk->parent->rate / sfc_divisors[idx];
 }
 
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7763.c b/arch/sh/kernel/cpu/sh4a/clock-sh7763.c
index 370cd47..9f40116 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7763.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7763.c
@@ -22,7 +22,7 @@
 
 static void master_clk_init(struct clk *clk)
 {
-	clk->rate *= p0fc_divisors[(ctrl_inl(FRQCR) >> 4) & 0x07];
+	clk->rate *= p0fc_divisors[(__raw_readl(FRQCR) >> 4) & 0x07];
 }
 
 static struct clk_ops sh7763_master_clk_ops = {
@@ -31,7 +31,7 @@
 
 static unsigned long module_clk_recalc(struct clk *clk)
 {
-	int idx = ((ctrl_inl(FRQCR) >> 4) & 0x07);
+	int idx = ((__raw_readl(FRQCR) >> 4) & 0x07);
 	return clk->parent->rate / p0fc_divisors[idx];
 }
 
@@ -41,7 +41,7 @@
 
 static unsigned long bus_clk_recalc(struct clk *clk)
 {
-	int idx = ((ctrl_inl(FRQCR) >> 16) & 0x07);
+	int idx = ((__raw_readl(FRQCR) >> 16) & 0x07);
 	return clk->parent->rate / bfc_divisors[idx];
 }
 
@@ -68,7 +68,7 @@
 
 static unsigned long shyway_clk_recalc(struct clk *clk)
 {
-	int idx = ((ctrl_inl(FRQCR) >> 20) & 0x07);
+	int idx = ((__raw_readl(FRQCR) >> 20) & 0x07);
 	return clk->parent->rate / cfc_divisors[idx];
 }
 
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7770.c b/arch/sh/kernel/cpu/sh4a/clock-sh7770.c
index e0b8967..9e33543 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7770.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7770.c
@@ -21,7 +21,7 @@
 
 static void master_clk_init(struct clk *clk)
 {
-	clk->rate *= pfc_divisors[(ctrl_inl(FRQCR) >> 28) & 0x000f];
+	clk->rate *= pfc_divisors[(__raw_readl(FRQCR) >> 28) & 0x000f];
 }
 
 static struct clk_ops sh7770_master_clk_ops = {
@@ -30,7 +30,7 @@
 
 static unsigned long module_clk_recalc(struct clk *clk)
 {
-	int idx = ((ctrl_inl(FRQCR) >> 28) & 0x000f);
+	int idx = ((__raw_readl(FRQCR) >> 28) & 0x000f);
 	return clk->parent->rate / pfc_divisors[idx];
 }
 
@@ -40,7 +40,7 @@
 
 static unsigned long bus_clk_recalc(struct clk *clk)
 {
-	int idx = (ctrl_inl(FRQCR) & 0x000f);
+	int idx = (__raw_readl(FRQCR) & 0x000f);
 	return clk->parent->rate / bfc_divisors[idx];
 }
 
@@ -50,7 +50,7 @@
 
 static unsigned long cpu_clk_recalc(struct clk *clk)
 {
-	int idx = ((ctrl_inl(FRQCR) >> 24) & 0x000f);
+	int idx = ((__raw_readl(FRQCR) >> 24) & 0x000f);
 	return clk->parent->rate / ifc_divisors[idx];
 }
 
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7780.c b/arch/sh/kernel/cpu/sh4a/clock-sh7780.c
index a249d82..150963a 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7780.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7780.c
@@ -22,7 +22,7 @@
 
 static void master_clk_init(struct clk *clk)
 {
-	clk->rate *= pfc_divisors[ctrl_inl(FRQCR) & 0x0003];
+	clk->rate *= pfc_divisors[__raw_readl(FRQCR) & 0x0003];
 }
 
 static struct clk_ops sh7780_master_clk_ops = {
@@ -31,7 +31,7 @@
 
 static unsigned long module_clk_recalc(struct clk *clk)
 {
-	int idx = (ctrl_inl(FRQCR) & 0x0003);
+	int idx = (__raw_readl(FRQCR) & 0x0003);
 	return clk->parent->rate / pfc_divisors[idx];
 }
 
@@ -41,7 +41,7 @@
 
 static unsigned long bus_clk_recalc(struct clk *clk)
 {
-	int idx = ((ctrl_inl(FRQCR) >> 16) & 0x0007);
+	int idx = ((__raw_readl(FRQCR) >> 16) & 0x0007);
 	return clk->parent->rate / bfc_divisors[idx];
 }
 
@@ -51,7 +51,7 @@
 
 static unsigned long cpu_clk_recalc(struct clk *clk)
 {
-	int idx = ((ctrl_inl(FRQCR) >> 24) & 0x0001);
+	int idx = ((__raw_readl(FRQCR) >> 24) & 0x0001);
 	return clk->parent->rate / ifc_divisors[idx];
 }
 
@@ -74,7 +74,7 @@
 
 static unsigned long shyway_clk_recalc(struct clk *clk)
 {
-	int idx = ((ctrl_inl(FRQCR) >> 20) & 0x0007);
+	int idx = ((__raw_readl(FRQCR) >> 20) & 0x0007);
 	return clk->parent->rate / cfc_divisors[idx];
 }
 
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7785.c b/arch/sh/kernel/cpu/sh4a/clock-sh7785.c
index 73abfbf..d997f0a 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7785.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7785.c
@@ -57,11 +57,15 @@
 static unsigned int div2[] = { 1, 2, 4, 6, 8, 12, 16, 18,
 			       24, 32, 36, 48 };
 
-static struct clk_div_mult_table div4_table = {
+static struct clk_div_mult_table div4_div_mult_table = {
 	.divisors = div2,
 	.nr_divisors = ARRAY_SIZE(div2),
 };
 
+static struct clk_div4_table div4_table = {
+	.div_mult_table = &div4_div_mult_table,
+};
+
 enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_DDR, DIV4_GA,
 	DIV4_DU, DIV4_P, DIV4_NR };
 
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7786.c b/arch/sh/kernel/cpu/sh4a/clock-sh7786.c
index a0e8869..af69fd4 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7786.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7786.c
@@ -3,11 +3,7 @@
  *
  * SH7786 support for the clock framework
  *
- * Copyright (C) 2008, 2009  Renesas Solutions Corp.
- * Kuninori Morimoto <morimoto.kuninori@renesas.com>
- *
- * Based on SH7785
- *  Copyright (C) 2007  Paul Mundt
+ *  Copyright (C) 2010  Paul Mundt
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
@@ -15,127 +11,127 @@
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/io.h>
 #include <asm/clock.h>
 #include <asm/freq.h>
-#include <asm/io.h>
-
-static int ifc_divisors[] = { 1, 2, 4, 1 };
-static int sfc_divisors[] = { 1, 1, 4, 1 };
-static int bfc_divisors[] = { 1, 1, 1, 1, 1, 12, 16, 1,
-			     24, 32, 1, 1, 1, 1, 1, 1 };
-static int mfc_divisors[] = { 1, 1, 4, 1 };
-static int pfc_divisors[] = { 1, 1, 1, 1, 1, 1, 16, 1,
-			      24, 32, 1, 48, 1, 1, 1, 1 };
-
-static void master_clk_init(struct clk *clk)
-{
-	clk->rate *= pfc_divisors[ctrl_inl(FRQMR1) & 0x000f];
-}
-
-static struct clk_ops sh7786_master_clk_ops = {
-	.init		= master_clk_init,
-};
-
-static unsigned long module_clk_recalc(struct clk *clk)
-{
-	int idx = (ctrl_inl(FRQMR1) & 0x000f);
-	return clk->parent->rate / pfc_divisors[idx];
-}
-
-static struct clk_ops sh7786_module_clk_ops = {
-	.recalc		= module_clk_recalc,
-};
-
-static unsigned long bus_clk_recalc(struct clk *clk)
-{
-	int idx = ((ctrl_inl(FRQMR1) >> 16) & 0x000f);
-	return clk->parent->rate / bfc_divisors[idx];
-}
-
-static struct clk_ops sh7786_bus_clk_ops = {
-	.recalc		= bus_clk_recalc,
-};
-
-static unsigned long cpu_clk_recalc(struct clk *clk)
-{
-	int idx = ((ctrl_inl(FRQMR1) >> 28) & 0x0003);
-	return clk->parent->rate / ifc_divisors[idx];
-}
-
-static struct clk_ops sh7786_cpu_clk_ops = {
-	.recalc		= cpu_clk_recalc,
-};
-
-static struct clk_ops *sh7786_clk_ops[] = {
-	&sh7786_master_clk_ops,
-	&sh7786_module_clk_ops,
-	&sh7786_bus_clk_ops,
-	&sh7786_cpu_clk_ops,
-};
-
-void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
-{
-	if (idx < ARRAY_SIZE(sh7786_clk_ops))
-		*ops = sh7786_clk_ops[idx];
-}
-
-static unsigned long shyway_clk_recalc(struct clk *clk)
-{
-	int idx = ((ctrl_inl(FRQMR1) >> 20) & 0x0003);
-	return clk->parent->rate / sfc_divisors[idx];
-}
-
-static struct clk_ops sh7786_shyway_clk_ops = {
-	.recalc		= shyway_clk_recalc,
-};
-
-static struct clk sh7786_shyway_clk = {
-	.name		= "shyway_clk",
-	.flags		= CLK_ENABLE_ON_INIT,
-	.ops		= &sh7786_shyway_clk_ops,
-};
-
-static unsigned long ddr_clk_recalc(struct clk *clk)
-{
-	int idx = ((ctrl_inl(FRQMR1) >> 12) & 0x0003);
-	return clk->parent->rate / mfc_divisors[idx];
-}
-
-static struct clk_ops sh7786_ddr_clk_ops = {
-	.recalc		= ddr_clk_recalc,
-};
-
-static struct clk sh7786_ddr_clk = {
-	.name		= "ddr_clk",
-	.flags		= CLK_ENABLE_ON_INIT,
-	.ops		= &sh7786_ddr_clk_ops,
-};
 
 /*
- * Additional SH7786-specific on-chip clocks that aren't already part of the
- * clock framework
+ * Default rate for the root input clock, reset this with clk_set_rate()
+ * from the platform code.
  */
-static struct clk *sh7786_onchip_clocks[] = {
-	&sh7786_shyway_clk,
-	&sh7786_ddr_clk,
+static struct clk extal_clk = {
+	.name		= "extal",
+	.id		= -1,
+	.rate		= 33333333,
+};
+
+static unsigned long pll_recalc(struct clk *clk)
+{
+	int multiplier;
+
+	/*
+	 * Clock modes 0, 1, and 2 use an x64 multiplier against PLL1,
+	 * while modes 3, 4, and 5 use an x32.
+	 */
+	multiplier = (sh_mv.mv_mode_pins() & 0xf) < 3 ? 64 : 32;
+
+	return clk->parent->rate * multiplier;
+}
+
+static struct clk_ops pll_clk_ops = {
+	.recalc		= pll_recalc,
+};
+
+static struct clk pll_clk = {
+	.name		= "pll_clk",
+	.id		= -1,
+	.ops		= &pll_clk_ops,
+	.parent		= &extal_clk,
+	.flags		= CLK_ENABLE_ON_INIT,
+};
+
+static struct clk *clks[] = {
+	&extal_clk,
+	&pll_clk,
+};
+
+static unsigned int div2[] = { 1, 2, 4, 6, 8, 12, 16, 18,
+			       24, 32, 36, 48 };
+
+static struct clk_div_mult_table div4_div_mult_table = {
+	.divisors = div2,
+	.nr_divisors = ARRAY_SIZE(div2),
+};
+
+static struct clk_div4_table div4_table = {
+	.div_mult_table = &div4_div_mult_table,
+};
+
+enum { DIV4_I, DIV4_SH, DIV4_B, DIV4_DDR, DIV4_DU, DIV4_P, DIV4_NR };
+
+#define DIV4(_str, _bit, _mask, _flags) \
+  SH_CLK_DIV4(_str, &pll_clk, FRQMR1, _bit, _mask, _flags)
+
+struct clk div4_clks[DIV4_NR] = {
+	[DIV4_P] = DIV4("peripheral_clk", 0, 0x0b40, 0),
+	[DIV4_DU] = DIV4("du_clk", 4, 0x0010, 0),
+	[DIV4_DDR] = DIV4("ddr_clk", 12, 0x0002, CLK_ENABLE_ON_INIT),
+	[DIV4_B] = DIV4("bus_clk", 16, 0x0360, CLK_ENABLE_ON_INIT),
+	[DIV4_SH] = DIV4("shyway_clk", 20, 0x0002, CLK_ENABLE_ON_INIT),
+	[DIV4_I] = DIV4("cpu_clk", 28, 0x0006, CLK_ENABLE_ON_INIT),
+};
+
+#define MSTPCR0		0xffc40030
+#define MSTPCR1		0xffc40034
+
+static struct clk mstp_clks[] = {
+	/* MSTPCR0 */
+	SH_CLK_MSTP32("scif_fck", 5, &div4_clks[DIV4_P], MSTPCR0, 29, 0),
+	SH_CLK_MSTP32("scif_fck", 4, &div4_clks[DIV4_P], MSTPCR0, 28, 0),
+	SH_CLK_MSTP32("scif_fck", 3, &div4_clks[DIV4_P], MSTPCR0, 27, 0),
+	SH_CLK_MSTP32("scif_fck", 2, &div4_clks[DIV4_P], MSTPCR0, 26, 0),
+	SH_CLK_MSTP32("scif_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 25, 0),
+	SH_CLK_MSTP32("scif_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 24, 0),
+	SH_CLK_MSTP32("ssi_fck", 3, &div4_clks[DIV4_P], MSTPCR0, 23, 0),
+	SH_CLK_MSTP32("ssi_fck", 2, &div4_clks[DIV4_P], MSTPCR0, 22, 0),
+	SH_CLK_MSTP32("ssi_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 21, 0),
+	SH_CLK_MSTP32("ssi_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 20, 0),
+	SH_CLK_MSTP32("hac_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 17, 0),
+	SH_CLK_MSTP32("hac_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 16, 0),
+	SH_CLK_MSTP32("i2c_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 15, 0),
+	SH_CLK_MSTP32("i2c_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 14, 0),
+	SH_CLK_MSTP32("tmu9_11_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 11, 0),
+	SH_CLK_MSTP32("tmu678_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 10, 0),
+	SH_CLK_MSTP32("tmu345_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 9, 0),
+	SH_CLK_MSTP32("tmu012_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 8, 0),
+	SH_CLK_MSTP32("sdif_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 5, 0),
+	SH_CLK_MSTP32("sdif_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 4, 0),
+	SH_CLK_MSTP32("hspi_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 2, 0),
+
+	/* MSTPCR1 */
+	SH_CLK_MSTP32("usb_fck", -1, NULL, MSTPCR1, 12, 0),
+	SH_CLK_MSTP32("pcie_fck", 2, NULL, MSTPCR1, 10, 0),
+	SH_CLK_MSTP32("pcie_fck", 1, NULL, MSTPCR1, 9, 0),
+	SH_CLK_MSTP32("pcie_fck", 0, NULL, MSTPCR1, 8, 0),
+	SH_CLK_MSTP32("dmac_11_6_fck", -1, NULL, MSTPCR1, 5, 0),
+	SH_CLK_MSTP32("dmac_5_0_fck", -1, NULL, MSTPCR1, 4, 0),
+	SH_CLK_MSTP32("du_fck", -1, NULL, MSTPCR1, 3, 0),
+	SH_CLK_MSTP32("ether_fck", -1, NULL, MSTPCR1, 2, 0),
 };
 
 int __init arch_clk_init(void)
 {
-	struct clk *clk;
 	int i, ret = 0;
 
-	cpg_clk_init();
+	for (i = 0; i < ARRAY_SIZE(clks); i++)
+		ret |= clk_register(clks[i]);
 
-	clk = clk_get(NULL, "master_clk");
-	for (i = 0; i < ARRAY_SIZE(sh7786_onchip_clocks); i++) {
-		struct clk *clkp = sh7786_onchip_clocks[i];
-
-		clkp->parent = clk;
-		ret |= clk_register(clkp);
-	}
-
-	clk_put(clk);
+	if (!ret)
+		ret = sh_clk_div4_register(div4_clks, ARRAY_SIZE(div4_clks),
+					   &div4_table);
+	if (!ret)
+		ret = sh_clk_mstp32_register(mstp_clks, ARRAY_SIZE(mstp_clks));
 
 	return ret;
 }
diff --git a/arch/sh/kernel/cpu/sh4a/clock-shx3.c b/arch/sh/kernel/cpu/sh4a/clock-shx3.c
index 23c27d3..e75c57b 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-shx3.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-shx3.c
@@ -33,7 +33,7 @@
 
 static void master_clk_init(struct clk *clk)
 {
-	clk->rate *= pfc_divisors[(ctrl_inl(FRQCR) >> PFC_POS) & PFC_MSK];
+	clk->rate *= pfc_divisors[(__raw_readl(FRQCR) >> PFC_POS) & PFC_MSK];
 }
 
 static struct clk_ops shx3_master_clk_ops = {
@@ -42,7 +42,7 @@
 
 static unsigned long module_clk_recalc(struct clk *clk)
 {
-	int idx = ((ctrl_inl(FRQCR) >> PFC_POS) & PFC_MSK);
+	int idx = ((__raw_readl(FRQCR) >> PFC_POS) & PFC_MSK);
 	return clk->parent->rate / pfc_divisors[idx];
 }
 
@@ -52,7 +52,7 @@
 
 static unsigned long bus_clk_recalc(struct clk *clk)
 {
-	int idx = ((ctrl_inl(FRQCR) >> BFC_POS) & BFC_MSK);
+	int idx = ((__raw_readl(FRQCR) >> BFC_POS) & BFC_MSK);
 	return clk->parent->rate / bfc_divisors[idx];
 }
 
@@ -62,7 +62,7 @@
 
 static unsigned long cpu_clk_recalc(struct clk *clk)
 {
-	int idx = ((ctrl_inl(FRQCR) >> IFC_POS) & IFC_MSK);
+	int idx = ((__raw_readl(FRQCR) >> IFC_POS) & IFC_MSK);
 	return clk->parent->rate / ifc_divisors[idx];
 }
 
@@ -85,7 +85,7 @@
 
 static unsigned long shyway_clk_recalc(struct clk *clk)
 {
-	int idx = ((ctrl_inl(FRQCR) >> CFC_POS) & CFC_MSK);
+	int idx = ((__raw_readl(FRQCR) >> CFC_POS) & CFC_MSK);
 	return clk->parent->rate / cfc_divisors[idx];
 }
 
diff --git a/arch/sh/kernel/cpu/sh4a/pinmux-sh7722.c b/arch/sh/kernel/cpu/sh4a/pinmux-sh7722.c
index cb9d07b..0688a75 100644
--- a/arch/sh/kernel/cpu/sh4a/pinmux-sh7722.c
+++ b/arch/sh/kernel/cpu/sh4a/pinmux-sh7722.c
@@ -278,6 +278,7 @@
 	HIZA8_LCDC, HIZA8_HIZ,
 	HIZA7_LCDC, HIZA7_HIZ,
 	HIZA6_LCDC, HIZA6_HIZ,
+	HIZB4_SIUA, HIZB4_HIZ,
 	HIZB1_VIO, HIZB1_HIZ,
 	HIZB0_VIO, HIZB0_HIZ,
 	HIZC15_IRQ7, HIZC15_HIZ,
@@ -546,7 +547,7 @@
 	PINMUX_DATA(VIO_VD2_MARK, PSE3_VIO, MSELB9_VIO2,
 		    HIZB0_VIO, FOE_VIO_VD2),
 	PINMUX_DATA(VIO_HD2_MARK, PSE3_VIO, MSELB9_VIO2,
-		    HIZB1_VIO, HIZB1_VIO, FCE_VIO_HD2),
+		    HIZB1_VIO, FCE_VIO_HD2),
 	PINMUX_DATA(VIO_CLK2_MARK, PSE3_VIO, MSELB9_VIO2,
 		    HIZB1_VIO, FRB_VIO_CLK2),
 
@@ -658,14 +659,14 @@
 	PINMUX_DATA(SDHICLK_MARK, SDHICLK),
 
 	/* SIU - Port A */
-	PINMUX_DATA(SIUAOLR_MARK, PSC13_SIUAOLR, SIUAOLR_SIOF1_SYNC),
-	PINMUX_DATA(SIUAOBT_MARK, PSC14_SIUAOBT, SIUAOBT_SIOF1_SCK),
-	PINMUX_DATA(SIUAISLD_MARK, PSC15_SIUAISLD, SIUAISLD_SIOF1_RXD),
-	PINMUX_DATA(SIUAILR_MARK, PSC11_SIUAILR, SIUAILR_SIOF1_SS2),
-	PINMUX_DATA(SIUAIBT_MARK, PSC12_SIUAIBT, SIUAIBT_SIOF1_SS1),
-	PINMUX_DATA(SIUAOSLD_MARK, PSB0_SIUAOSLD, SIUAOSLD_SIOF1_TXD),
-	PINMUX_DATA(SIUMCKA_MARK, PSE11_SIUMCKA_SIOF1_MCK, PSB1_SIUMCKA, PTK0),
-	PINMUX_DATA(SIUFCKA_MARK, PSE11_SIUFCKA, PTK0),
+	PINMUX_DATA(SIUAOLR_MARK, PSC13_SIUAOLR, HIZB4_SIUA, SIUAOLR_SIOF1_SYNC),
+	PINMUX_DATA(SIUAOBT_MARK, PSC14_SIUAOBT, HIZB4_SIUA, SIUAOBT_SIOF1_SCK),
+	PINMUX_DATA(SIUAISLD_MARK, PSC15_SIUAISLD, HIZB4_SIUA, SIUAISLD_SIOF1_RXD),
+	PINMUX_DATA(SIUAILR_MARK, PSC11_SIUAILR, HIZB4_SIUA, SIUAILR_SIOF1_SS2),
+	PINMUX_DATA(SIUAIBT_MARK, PSC12_SIUAIBT, HIZB4_SIUA, SIUAIBT_SIOF1_SS1),
+	PINMUX_DATA(SIUAOSLD_MARK, PSB0_SIUAOSLD, HIZB4_SIUA, SIUAOSLD_SIOF1_TXD),
+	PINMUX_DATA(SIUMCKA_MARK, PSE11_SIUMCKA_SIOF1_MCK, HIZB4_SIUA, PSB1_SIUMCKA, PTK0),
+	PINMUX_DATA(SIUFCKA_MARK, PSE11_SIUFCKA, HIZB4_SIUA, PTK0),
 
 	/* SIU - Port B */
 	PINMUX_DATA(SIUBOLR_MARK, PSB11_SIUBOLR, SIOSTRB1_SIUBOLR),
@@ -1612,7 +1613,7 @@
 		0, 0,
 		0, 0,
 		0, 0,
-		0, 0,
+		HIZB4_SIUA, HIZB4_HIZ,
 		0, 0,
 		0, 0,
 		HIZB1_VIO, HIZB1_HIZ,
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
index b5335b5..ef3f978 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
@@ -446,6 +446,8 @@
 
 enum {
 	UNUSED=0,
+	ENABLED,
+	DISABLED,
 
 	/* interrupt sources */
 	IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
@@ -461,7 +463,6 @@
 	SCIF0, SCIF1, SCIF2, SIOF0, SIOF1, SIO,
 	FLCTL_FLSTEI, FLCTL_FLENDI, FLCTL_FLTREQ0I, FLCTL_FLTREQ1I,
 	I2C_ALI, I2C_TACKI, I2C_WAITI, I2C_DTEI,
-	SDHI0, SDHI1, SDHI2, SDHI3,
 	CMT, TSIF, SIU, TWODG,
 	TMU0, TMU1, TMU2,
 	IRDA, JPU, LCDC,
@@ -494,8 +495,8 @@
 	INTC_VECT(FLCTL_FLTREQ0I, 0xdc0), INTC_VECT(FLCTL_FLTREQ1I, 0xde0),
 	INTC_VECT(I2C_ALI, 0xe00), INTC_VECT(I2C_TACKI, 0xe20),
 	INTC_VECT(I2C_WAITI, 0xe40), INTC_VECT(I2C_DTEI, 0xe60),
-	INTC_VECT(SDHI0, 0xe80), INTC_VECT(SDHI1, 0xea0),
-	INTC_VECT(SDHI2, 0xec0), INTC_VECT(SDHI3, 0xee0),
+	INTC_VECT(SDHI, 0xe80), INTC_VECT(SDHI, 0xea0),
+	INTC_VECT(SDHI, 0xec0), INTC_VECT(SDHI, 0xee0),
 	INTC_VECT(CMT, 0xf00), INTC_VECT(TSIF, 0xf20),
 	INTC_VECT(SIU, 0xf80), INTC_VECT(TWODG, 0xfa0),
 	INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420),
@@ -513,7 +514,6 @@
 	INTC_GROUP(FLCTL, FLCTL_FLSTEI, FLCTL_FLENDI,
 		   FLCTL_FLTREQ0I, FLCTL_FLTREQ1I),
 	INTC_GROUP(I2C, I2C_ALI, I2C_TACKI, I2C_WAITI, I2C_DTEI),
-	INTC_GROUP(SDHI, SDHI0, SDHI1, SDHI2, SDHI3),
 };
 
 static struct intc_mask_reg mask_registers[] __initdata = {
@@ -535,7 +535,7 @@
 	  { I2C_DTEI, I2C_WAITI, I2C_TACKI, I2C_ALI,
 	    FLCTL_FLTREQ1I, FLCTL_FLTREQ0I, FLCTL_FLENDI, FLCTL_FLSTEI } },
 	{ 0xa40800a0, 0xa40800e0, 8, /* IMR8 / IMCR8 */
-	  { SDHI3, SDHI2, SDHI1, SDHI0, 0, 0, TWODG, SIU } },
+	  { DISABLED, DISABLED, ENABLED, ENABLED, 0, 0, TWODG, SIU } },
 	{ 0xa40800a4, 0xa40800e4, 8, /* IMR9 / IMCR9 */
 	  { 0, 0, 0, CMT, 0, USB_USBI1, USB_USBI0, } },
 	{ 0xa40800a8, 0xa40800e8, 8, /* IMR10 / IMCR10 */
@@ -573,9 +573,13 @@
 	  { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
 };
 
-static DECLARE_INTC_DESC_ACK(intc_desc, "sh7722", vectors, groups,
-			     mask_registers, prio_registers, sense_registers,
-			     ack_registers);
+static struct intc_desc intc_desc __initdata = {
+	.name = "sh7722",
+	.force_enable = ENABLED,
+	.force_disable = DISABLED,
+	.hw = INTC_HW_DESC(vectors, groups, mask_registers,
+			   prio_registers, sense_registers, ack_registers),
+};
 
 void __init plat_irq_setup(void)
 {
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
index 772b926..85c61f6 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
@@ -592,14 +592,17 @@
 #define RAMCR_CACHE_L2FC	0x0002
 #define RAMCR_CACHE_L2E		0x0001
 #define L2_CACHE_ENABLE		(RAMCR_CACHE_L2E|RAMCR_CACHE_L2FC)
-void __uses_jump_to_uncached l2_cache_init(void)
+
+void l2_cache_init(void)
 {
 	/* Enable L2 cache */
-	ctrl_outl(L2_CACHE_ENABLE, RAMCR);
+	__raw_writel(L2_CACHE_ENABLE, RAMCR);
 }
 
 enum {
 	UNUSED=0,
+	ENABLED,
+	DISABLED,
 
 	/* interrupt sources */
 	IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
@@ -622,7 +625,6 @@
 	SCIFA_SCIFA1,
 	FLCTL_FLSTEI,FLCTL_FLTENDI,FLCTL_FLTREQ0I,FLCTL_FLTREQ1I,
 	I2C_ALI,I2C_TACKI,I2C_WAITI,I2C_DTEI,
-	SDHI0_SDHII0,SDHI0_SDHII1,SDHI0_SDHII2,
 	CMT_CMTI,
 	TSIF_TSIFI,
 	SIU_SIUI,
@@ -630,7 +632,6 @@
 	TMU0_TUNI0, TMU0_TUNI1, TMU0_TUNI2,
 	IRDA_IRDAI,
 	ATAPI_ATAPII,
-	SDHI1_SDHII0,SDHI1_SDHII1,SDHI1_SDHII2,
 	VEU2H1_VEU2HI,
 	LCDC_LCDCI,
 	TMU1_TUNI0,TMU1_TUNI1,TMU1_TUNI2,
@@ -701,9 +702,9 @@
 	INTC_VECT(I2C_WAITI,0xE40),
 	INTC_VECT(I2C_DTEI,0xE60),
 
-	INTC_VECT(SDHI0_SDHII0,0xE80),
-	INTC_VECT(SDHI0_SDHII1,0xEA0),
-	INTC_VECT(SDHI0_SDHII2,0xEC0),
+	INTC_VECT(SDHI0, 0xE80),
+	INTC_VECT(SDHI0, 0xEA0),
+	INTC_VECT(SDHI0, 0xEC0),
 
 	INTC_VECT(CMT_CMTI,0xF00),
 	INTC_VECT(TSIF_TSIFI,0xF20),
@@ -717,9 +718,9 @@
 	INTC_VECT(IRDA_IRDAI,0x480),
 	INTC_VECT(ATAPI_ATAPII,0x4A0),
 
-	INTC_VECT(SDHI1_SDHII0,0x4E0),
-	INTC_VECT(SDHI1_SDHII1,0x500),
-	INTC_VECT(SDHI1_SDHII2,0x520),
+	INTC_VECT(SDHI1, 0x4E0),
+	INTC_VECT(SDHI1, 0x500),
+	INTC_VECT(SDHI1, 0x520),
 
 	INTC_VECT(VEU2H1_VEU2HI,0x560),
 	INTC_VECT(LCDC_LCDCI,0x580),
@@ -738,15 +739,14 @@
 	INTC_GROUP(FLCTL,FLCTL_FLSTEI,FLCTL_FLTENDI,FLCTL_FLTREQ0I,FLCTL_FLTREQ1I),
 	INTC_GROUP(I2C,I2C_ALI,I2C_TACKI,I2C_WAITI,I2C_DTEI),
 	INTC_GROUP(_2DG, _2DG_TRI,_2DG_INI,_2DG_CEI),
-	INTC_GROUP(SDHI1, SDHI1_SDHII0,SDHI1_SDHII1,SDHI1_SDHII2),
 	INTC_GROUP(RTC, RTC_ATI,RTC_PRI,RTC_CUI),
 	INTC_GROUP(DMAC1B, DMAC1B_DEI4,DMAC1B_DEI5,DMAC1B_DADERR),
-	INTC_GROUP(SDHI0,SDHI0_SDHII0,SDHI0_SDHII1,SDHI0_SDHII2),
 };
 
 static struct intc_mask_reg mask_registers[] __initdata = {
 	{ 0xa4080080, 0xa40800c0, 8, /* IMR0 / IMCR0 */
-	  { 0,  TMU1_TUNI2,TMU1_TUNI1,TMU1_TUNI0,0,SDHI1_SDHII2,SDHI1_SDHII1,SDHI1_SDHII0} },
+	  { 0, TMU1_TUNI2, TMU1_TUNI1, TMU1_TUNI0,
+	    0, DISABLED, ENABLED, ENABLED } },
 	{ 0xa4080084, 0xa40800c4, 8, /* IMR1 / IMCR1 */
 	  { VIO_VOUI, VIO_VEU2HI,VIO_BEUI,VIO_CEUI,DMAC0A_DEI3,DMAC0A_DEI2,DMAC0A_DEI1,DMAC0A_DEI0 } },
 	{ 0xa4080088, 0xa40800c8, 8, /* IMR2 / IMCR2 */
@@ -763,7 +763,8 @@
 	  { I2C_DTEI, I2C_WAITI, I2C_TACKI, I2C_ALI,
 	    FLCTL_FLTREQ1I, FLCTL_FLTREQ0I, FLCTL_FLTENDI, FLCTL_FLSTEI } },
 	{ 0xa40800a0, 0xa40800e0, 8, /* IMR8 / IMCR8 */
-	  { 0,SDHI0_SDHII2,SDHI0_SDHII1,SDHI0_SDHII0,0,0,SCIFA_SCIFA2,SIU_SIUI } },
+	  { 0, DISABLED, ENABLED, ENABLED,
+	    0, 0, SCIFA_SCIFA2, SIU_SIUI } },
 	{ 0xa40800a4, 0xa40800e4, 8, /* IMR9 / IMCR9 */
 	  { 0, 0, 0, CMT_CMTI, 0, 0, USB_USI0,0 } },
 	{ 0xa40800a8, 0xa40800e8, 8, /* IMR10 / IMCR10 */
@@ -803,9 +804,13 @@
 	  { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
 };
 
-static DECLARE_INTC_DESC_ACK(intc_desc, "sh7723", vectors, groups,
-			     mask_registers, prio_registers, sense_registers,
-			     ack_registers);
+static struct intc_desc intc_desc __initdata = {
+	.name = "sh7723",
+	.force_enable = ENABLED,
+	.force_disable = DISABLED,
+	.hw = INTC_HW_DESC(vectors, groups, mask_registers,
+			   prio_registers, sense_registers, ack_registers),
+};
 
 void __init plat_irq_setup(void)
 {
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
index d32f96c..31e3451 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
@@ -714,14 +714,17 @@
 #define RAMCR_CACHE_L2FC	0x0002
 #define RAMCR_CACHE_L2E		0x0001
 #define L2_CACHE_ENABLE		(RAMCR_CACHE_L2E|RAMCR_CACHE_L2FC)
-void __uses_jump_to_uncached l2_cache_init(void)
+
+void l2_cache_init(void)
 {
 	/* Enable L2 cache */
-	ctrl_outl(L2_CACHE_ENABLE, RAMCR);
+	__raw_writel(L2_CACHE_ENABLE, RAMCR);
 }
 
 enum {
 	UNUSED = 0,
+	ENABLED,
+	DISABLED,
 
 	/* interrupt sources */
 	IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
@@ -750,14 +753,12 @@
 	ETHI,
 	I2C1_ALI, I2C1_TACKI, I2C1_WAITI, I2C1_DTEI,
 	I2C0_ALI, I2C0_TACKI, I2C0_WAITI, I2C0_DTEI,
-	SDHI0_SDHII0, SDHI0_SDHII1, SDHI0_SDHII2, SDHI0_SDHII3,
 	CMT,
 	TSIF,
 	FSI,
 	SCIFA5,
 	TMU0_TUNI0, TMU0_TUNI1, TMU0_TUNI2,
 	IRDA,
-	SDHI1_SDHII0, SDHI1_SDHII1, SDHI1_SDHII2,
 	JPU,
 	_2DDMAC,
 	MMC_MMC2I, MMC_MMC3I,
@@ -839,10 +840,10 @@
 	INTC_VECT(I2C0_WAITI, 0xE40),
 	INTC_VECT(I2C0_DTEI, 0xE60),
 
-	INTC_VECT(SDHI0_SDHII0, 0xE80),
-	INTC_VECT(SDHI0_SDHII1, 0xEA0),
-	INTC_VECT(SDHI0_SDHII2, 0xEC0),
-	INTC_VECT(SDHI0_SDHII3, 0xEE0),
+	INTC_VECT(SDHI0, 0xE80),
+	INTC_VECT(SDHI0, 0xEA0),
+	INTC_VECT(SDHI0, 0xEC0),
+	INTC_VECT(SDHI0, 0xEE0),
 
 	INTC_VECT(CMT,    0xF00),
 	INTC_VECT(TSIF,   0xF20),
@@ -855,9 +856,9 @@
 
 	INTC_VECT(IRDA,    0x480),
 
-	INTC_VECT(SDHI1_SDHII0, 0x4E0),
-	INTC_VECT(SDHI1_SDHII1, 0x500),
-	INTC_VECT(SDHI1_SDHII2, 0x520),
+	INTC_VECT(SDHI1, 0x4E0),
+	INTC_VECT(SDHI1, 0x500),
+	INTC_VECT(SDHI1, 0x520),
 
 	INTC_VECT(JPU, 0x560),
 	INTC_VECT(_2DDMAC, 0x4A0),
@@ -883,8 +884,6 @@
 	INTC_GROUP(DMAC0B, DMAC0B_DEI4, DMAC0B_DEI5, DMAC0B_DADERR),
 	INTC_GROUP(I2C0, I2C0_ALI, I2C0_TACKI, I2C0_WAITI, I2C0_DTEI),
 	INTC_GROUP(I2C1, I2C1_ALI, I2C1_TACKI, I2C1_WAITI, I2C1_DTEI),
-	INTC_GROUP(SDHI0, SDHI0_SDHII0, SDHI0_SDHII1, SDHI0_SDHII2, SDHI0_SDHII3),
-	INTC_GROUP(SDHI1, SDHI1_SDHII0, SDHI1_SDHII1, SDHI1_SDHII2),
 	INTC_GROUP(SPU, SPU_SPUI0, SPU_SPUI1),
 	INTC_GROUP(MMCIF, MMC_MMC2I, MMC_MMC3I),
 };
@@ -892,7 +891,7 @@
 static struct intc_mask_reg mask_registers[] __initdata = {
 	{ 0xa4080080, 0xa40800c0, 8, /* IMR0 / IMCR0 */
 	  { 0, TMU1_TUNI2, TMU1_TUNI1, TMU1_TUNI0,
-	    0, SDHI1_SDHII2, SDHI1_SDHII1, SDHI1_SDHII0 } },
+	    0, DISABLED, ENABLED, ENABLED } },
 	{ 0xa4080084, 0xa40800c4, 8, /* IMR1 / IMCR1 */
 	  { VIO_VOU, VIO_VEU1, VIO_BEU0, VIO_CEU0,
 	    DMAC0A_DEI3, DMAC0A_DEI2, DMAC0A_DEI1, DMAC0A_DEI0 } },
@@ -914,7 +913,7 @@
 	  { I2C0_DTEI, I2C0_WAITI, I2C0_TACKI, I2C0_ALI,
 	    I2C1_DTEI, I2C1_WAITI, I2C1_TACKI, I2C1_ALI } },
 	{ 0xa40800a0, 0xa40800e0, 8, /* IMR8 / IMCR8 */
-	  { SDHI0_SDHII3, SDHI0_SDHII2, SDHI0_SDHII1, SDHI0_SDHII0,
+	  { DISABLED, DISABLED, ENABLED, ENABLED,
 	    0, 0, SCIFA5, FSI } },
 	{ 0xa40800a4, 0xa40800e4, 8, /* IMR9 / IMCR9 */
 	  { 0, 0, 0, CMT, 0, USB1, USB0, 0 } },
@@ -961,9 +960,13 @@
 	  { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
 };
 
-static DECLARE_INTC_DESC_ACK(intc_desc, "sh7724", vectors, groups,
-			     mask_registers, prio_registers, sense_registers,
-			     ack_registers);
+static struct intc_desc intc_desc __initdata = {
+	.name = "sh7724",
+	.force_enable = ENABLED,
+	.force_disable = DISABLED,
+	.hw = INTC_HW_DESC(vectors, groups, mask_registers,
+			   prio_registers, sense_registers, ack_registers),
+};
 
 void __init plat_irq_setup(void)
 {
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c
index 37e32ef..e75edf5 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c
@@ -487,17 +487,17 @@
 void __init plat_irq_setup(void)
 {
 	/* disable IRQ3-0 + IRQ7-4 */
-	ctrl_outl(0xff000000, INTC_INTMSK0);
+	__raw_writel(0xff000000, INTC_INTMSK0);
 
 	/* disable IRL3-0 + IRL7-4 */
-	ctrl_outl(0xc0000000, INTC_INTMSK1);
-	ctrl_outl(0xfffefffe, INTC_INTMSK2);
+	__raw_writel(0xc0000000, INTC_INTMSK1);
+	__raw_writel(0xfffefffe, INTC_INTMSK2);
 
 	/* select IRL mode for IRL3-0 + IRL7-4 */
-	ctrl_outl(ctrl_inl(INTC_ICR0) & ~0x00c00000, INTC_ICR0);
+	__raw_writel(__raw_readl(INTC_ICR0) & ~0x00c00000, INTC_ICR0);
 
 	/* disable holding function, ie enable "SH-4 Mode" */
-	ctrl_outl(ctrl_inl(INTC_ICR0) | 0x00200000, INTC_ICR0);
+	__raw_writel(__raw_readl(INTC_ICR0) | 0x00200000, INTC_ICR0);
 
 	register_intc_controller(&intc_desc);
 }
@@ -507,32 +507,32 @@
 	switch (mode) {
 	case IRQ_MODE_IRQ7654:
 		/* select IRQ mode for IRL7-4 */
-		ctrl_outl(ctrl_inl(INTC_ICR0) | 0x00400000, INTC_ICR0);
+		__raw_writel(__raw_readl(INTC_ICR0) | 0x00400000, INTC_ICR0);
 		register_intc_controller(&intc_desc_irq4567);
 		break;
 	case IRQ_MODE_IRQ3210:
 		/* select IRQ mode for IRL3-0 */
-		ctrl_outl(ctrl_inl(INTC_ICR0) | 0x00800000, INTC_ICR0);
+		__raw_writel(__raw_readl(INTC_ICR0) | 0x00800000, INTC_ICR0);
 		register_intc_controller(&intc_desc_irq0123);
 		break;
 	case IRQ_MODE_IRL7654:
 		/* enable IRL7-4 but don't provide any masking */
-		ctrl_outl(0x40000000, INTC_INTMSKCLR1);
-		ctrl_outl(0x0000fffe, INTC_INTMSKCLR2);
+		__raw_writel(0x40000000, INTC_INTMSKCLR1);
+		__raw_writel(0x0000fffe, INTC_INTMSKCLR2);
 		break;
 	case IRQ_MODE_IRL3210:
 		/* enable IRL0-3 but don't provide any masking */
-		ctrl_outl(0x80000000, INTC_INTMSKCLR1);
-		ctrl_outl(0xfffe0000, INTC_INTMSKCLR2);
+		__raw_writel(0x80000000, INTC_INTMSKCLR1);
+		__raw_writel(0xfffe0000, INTC_INTMSKCLR2);
 		break;
 	case IRQ_MODE_IRL7654_MASK:
 		/* enable IRL7-4 and mask using cpu intc controller */
-		ctrl_outl(0x40000000, INTC_INTMSKCLR1);
+		__raw_writel(0x40000000, INTC_INTMSKCLR1);
 		register_intc_controller(&intc_desc_irl4567);
 		break;
 	case IRQ_MODE_IRL3210_MASK:
 		/* enable IRL0-3 and mask using cpu intc controller */
-		ctrl_outl(0x80000000, INTC_INTMSKCLR1);
+		__raw_writel(0x80000000, INTC_INTMSKCLR1);
 		register_intc_controller(&intc_desc_irl0123);
 		break;
 	default:
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7763.c b/arch/sh/kernel/cpu/sh4a/setup-sh7763.c
index 6aba26f..7f6b0a5 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7763.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7763.c
@@ -538,11 +538,11 @@
 void __init plat_irq_setup(void)
 {
 	/* disable IRQ7-0 */
-	ctrl_outl(0xff000000, INTC_INTMSK0);
+	__raw_writel(0xff000000, INTC_INTMSK0);
 
 	/* disable IRL3-0 + IRL7-4 */
-	ctrl_outl(0xc0000000, INTC_INTMSK1);
-	ctrl_outl(0xfffefffe, INTC_INTMSK2);
+	__raw_writel(0xc0000000, INTC_INTMSK1);
+	__raw_writel(0xfffefffe, INTC_INTMSK2);
 
 	register_intc_controller(&intc_desc);
 }
@@ -552,27 +552,27 @@
 	switch (mode) {
 	case IRQ_MODE_IRQ:
 		/* select IRQ mode for IRL3-0 + IRL7-4 */
-		ctrl_outl(ctrl_inl(INTC_ICR0) | 0x00c00000, INTC_ICR0);
+		__raw_writel(__raw_readl(INTC_ICR0) | 0x00c00000, INTC_ICR0);
 		register_intc_controller(&intc_irq_desc);
 		break;
 	case IRQ_MODE_IRL7654:
 		/* enable IRL7-4 but don't provide any masking */
-		ctrl_outl(0x40000000, INTC_INTMSKCLR1);
-		ctrl_outl(0x0000fffe, INTC_INTMSKCLR2);
+		__raw_writel(0x40000000, INTC_INTMSKCLR1);
+		__raw_writel(0x0000fffe, INTC_INTMSKCLR2);
 		break;
 	case IRQ_MODE_IRL3210:
 		/* enable IRL0-3 but don't provide any masking */
-		ctrl_outl(0x80000000, INTC_INTMSKCLR1);
-		ctrl_outl(0xfffe0000, INTC_INTMSKCLR2);
+		__raw_writel(0x80000000, INTC_INTMSKCLR1);
+		__raw_writel(0xfffe0000, INTC_INTMSKCLR2);
 		break;
 	case IRQ_MODE_IRL7654_MASK:
 		/* enable IRL7-4 and mask using cpu intc controller */
-		ctrl_outl(0x40000000, INTC_INTMSKCLR1);
+		__raw_writel(0x40000000, INTC_INTMSKCLR1);
 		register_intc_controller(&intc_irl7654_desc);
 		break;
 	case IRQ_MODE_IRL3210_MASK:
 		/* enable IRL0-3 and mask using cpu intc controller */
-		ctrl_outl(0x80000000, INTC_INTMSKCLR1);
+		__raw_writel(0x80000000, INTC_INTMSKCLR1);
 		register_intc_controller(&intc_irl3210_desc);
 		break;
 	default:
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7770.c b/arch/sh/kernel/cpu/sh4a/setup-sh7770.c
index c1643bc..86d681e 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7770.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7770.c
@@ -694,17 +694,17 @@
 void __init plat_irq_setup(void)
 {
 	/* disable IRQ7-0 */
-	ctrl_outl(0xff000000, INTC_INTMSK0);
+	__raw_writel(0xff000000, INTC_INTMSK0);
 
 	/* disable IRL3-0 + IRL7-4 */
-	ctrl_outl(0xc0000000, INTC_INTMSK1);
-	ctrl_outl(0xfffefffe, INTC_INTMSK2);
+	__raw_writel(0xc0000000, INTC_INTMSK1);
+	__raw_writel(0xfffefffe, INTC_INTMSK2);
 
 	/* select IRL mode for IRL3-0 + IRL7-4 */
-	ctrl_outl(ctrl_inl(INTC_ICR0) & ~0x00c00000, INTC_ICR0);
+	__raw_writel(__raw_readl(INTC_ICR0) & ~0x00c00000, INTC_ICR0);
 
 	/* disable holding function, ie enable "SH-4 Mode" */
-	ctrl_outl(ctrl_inl(INTC_ICR0) | 0x00200000, INTC_ICR0);
+	__raw_writel(__raw_readl(INTC_ICR0) | 0x00200000, INTC_ICR0);
 
 	register_intc_controller(&intc_desc);
 }
@@ -714,27 +714,27 @@
 	switch (mode) {
 	case IRQ_MODE_IRQ:
 		/* select IRQ mode for IRL3-0 + IRL7-4 */
-		ctrl_outl(ctrl_inl(INTC_ICR0) | 0x00c00000, INTC_ICR0);
+		__raw_writel(__raw_readl(INTC_ICR0) | 0x00c00000, INTC_ICR0);
 		register_intc_controller(&intc_irq_desc);
 		break;
 	case IRQ_MODE_IRL7654:
 		/* enable IRL7-4 but don't provide any masking */
-		ctrl_outl(0x40000000, INTC_INTMSKCLR1);
-		ctrl_outl(0x0000fffe, INTC_INTMSKCLR2);
+		__raw_writel(0x40000000, INTC_INTMSKCLR1);
+		__raw_writel(0x0000fffe, INTC_INTMSKCLR2);
 		break;
 	case IRQ_MODE_IRL3210:
 		/* enable IRL0-3 but don't provide any masking */
-		ctrl_outl(0x80000000, INTC_INTMSKCLR1);
-		ctrl_outl(0xfffe0000, INTC_INTMSKCLR2);
+		__raw_writel(0x80000000, INTC_INTMSKCLR1);
+		__raw_writel(0xfffe0000, INTC_INTMSKCLR2);
 		break;
 	case IRQ_MODE_IRL7654_MASK:
 		/* enable IRL7-4 and mask using cpu intc controller */
-		ctrl_outl(0x40000000, INTC_INTMSKCLR1);
+		__raw_writel(0x40000000, INTC_INTMSKCLR1);
 		register_intc_controller(&intc_irl7654_desc);
 		break;
 	case IRQ_MODE_IRL3210_MASK:
 		/* enable IRL0-3 and mask using cpu intc controller */
-		ctrl_outl(0x80000000, INTC_INTMSKCLR1);
+		__raw_writel(0x80000000, INTC_INTMSKCLR1);
 		register_intc_controller(&intc_irl3210_desc);
 		break;
 	default:
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
index c310558..f8f2161 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
@@ -461,17 +461,17 @@
 void __init plat_irq_setup(void)
 {
 	/* disable IRQ7-0 */
-	ctrl_outl(0xff000000, INTC_INTMSK0);
+	__raw_writel(0xff000000, INTC_INTMSK0);
 
 	/* disable IRL3-0 + IRL7-4 */
-	ctrl_outl(0xc0000000, INTC_INTMSK1);
-	ctrl_outl(0xfffefffe, INTC_INTMSK2);
+	__raw_writel(0xc0000000, INTC_INTMSK1);
+	__raw_writel(0xfffefffe, INTC_INTMSK2);
 
 	/* select IRL mode for IRL3-0 + IRL7-4 */
-	ctrl_outl(ctrl_inl(INTC_ICR0) & ~0x00c00000, INTC_ICR0);
+	__raw_writel(__raw_readl(INTC_ICR0) & ~0x00c00000, INTC_ICR0);
 
 	/* disable holding function, ie enable "SH-4 Mode" */
-	ctrl_outl(ctrl_inl(INTC_ICR0) | 0x00200000, INTC_ICR0);
+	__raw_writel(__raw_readl(INTC_ICR0) | 0x00200000, INTC_ICR0);
 
 	register_intc_controller(&intc_desc);
 }
@@ -481,27 +481,27 @@
 	switch (mode) {
 	case IRQ_MODE_IRQ:
 		/* select IRQ mode for IRL3-0 + IRL7-4 */
-		ctrl_outl(ctrl_inl(INTC_ICR0) | 0x00c00000, INTC_ICR0);
+		__raw_writel(__raw_readl(INTC_ICR0) | 0x00c00000, INTC_ICR0);
 		register_intc_controller(&intc_irq_desc);
 		break;
 	case IRQ_MODE_IRL7654:
 		/* enable IRL7-4 but don't provide any masking */
-		ctrl_outl(0x40000000, INTC_INTMSKCLR1);
-		ctrl_outl(0x0000fffe, INTC_INTMSKCLR2);
+		__raw_writel(0x40000000, INTC_INTMSKCLR1);
+		__raw_writel(0x0000fffe, INTC_INTMSKCLR2);
 		break;
 	case IRQ_MODE_IRL3210:
 		/* enable IRL0-3 but don't provide any masking */
-		ctrl_outl(0x80000000, INTC_INTMSKCLR1);
-		ctrl_outl(0xfffe0000, INTC_INTMSKCLR2);
+		__raw_writel(0x80000000, INTC_INTMSKCLR1);
+		__raw_writel(0xfffe0000, INTC_INTMSKCLR2);
 		break;
 	case IRQ_MODE_IRL7654_MASK:
 		/* enable IRL7-4 and mask using cpu intc controller */
-		ctrl_outl(0x40000000, INTC_INTMSKCLR1);
+		__raw_writel(0x40000000, INTC_INTMSKCLR1);
 		register_intc_controller(&intc_irl7654_desc);
 		break;
 	case IRQ_MODE_IRL3210_MASK:
 		/* enable IRL0-3 and mask using cpu intc controller */
-		ctrl_outl(0x80000000, INTC_INTMSKCLR1);
+		__raw_writel(0x80000000, INTC_INTMSKCLR1);
 		register_intc_controller(&intc_irl3210_desc);
 		break;
 	default:
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
index f685b9b..23448d8 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
@@ -541,17 +541,17 @@
 void __init plat_irq_setup(void)
 {
 	/* disable IRQ3-0 + IRQ7-4 */
-	ctrl_outl(0xff000000, INTC_INTMSK0);
+	__raw_writel(0xff000000, INTC_INTMSK0);
 
 	/* disable IRL3-0 + IRL7-4 */
-	ctrl_outl(0xc0000000, INTC_INTMSK1);
-	ctrl_outl(0xfffefffe, INTC_INTMSK2);
+	__raw_writel(0xc0000000, INTC_INTMSK1);
+	__raw_writel(0xfffefffe, INTC_INTMSK2);
 
 	/* select IRL mode for IRL3-0 + IRL7-4 */
-	ctrl_outl(ctrl_inl(INTC_ICR0) & ~0x00c00000, INTC_ICR0);
+	__raw_writel(__raw_readl(INTC_ICR0) & ~0x00c00000, INTC_ICR0);
 
 	/* disable holding function, ie enable "SH-4 Mode" */
-	ctrl_outl(ctrl_inl(INTC_ICR0) | 0x00200000, INTC_ICR0);
+	__raw_writel(__raw_readl(INTC_ICR0) | 0x00200000, INTC_ICR0);
 
 	register_intc_controller(&intc_desc);
 }
@@ -561,32 +561,32 @@
 	switch (mode) {
 	case IRQ_MODE_IRQ7654:
 		/* select IRQ mode for IRL7-4 */
-		ctrl_outl(ctrl_inl(INTC_ICR0) | 0x00400000, INTC_ICR0);
+		__raw_writel(__raw_readl(INTC_ICR0) | 0x00400000, INTC_ICR0);
 		register_intc_controller(&intc_desc_irq4567);
 		break;
 	case IRQ_MODE_IRQ3210:
 		/* select IRQ mode for IRL3-0 */
-		ctrl_outl(ctrl_inl(INTC_ICR0) | 0x00800000, INTC_ICR0);
+		__raw_writel(__raw_readl(INTC_ICR0) | 0x00800000, INTC_ICR0);
 		register_intc_controller(&intc_desc_irq0123);
 		break;
 	case IRQ_MODE_IRL7654:
 		/* enable IRL7-4 but don't provide any masking */
-		ctrl_outl(0x40000000, INTC_INTMSKCLR1);
-		ctrl_outl(0x0000fffe, INTC_INTMSKCLR2);
+		__raw_writel(0x40000000, INTC_INTMSKCLR1);
+		__raw_writel(0x0000fffe, INTC_INTMSKCLR2);
 		break;
 	case IRQ_MODE_IRL3210:
 		/* enable IRL0-3 but don't provide any masking */
-		ctrl_outl(0x80000000, INTC_INTMSKCLR1);
-		ctrl_outl(0xfffe0000, INTC_INTMSKCLR2);
+		__raw_writel(0x80000000, INTC_INTMSKCLR1);
+		__raw_writel(0xfffe0000, INTC_INTMSKCLR2);
 		break;
 	case IRQ_MODE_IRL7654_MASK:
 		/* enable IRL7-4 and mask using cpu intc controller */
-		ctrl_outl(0x40000000, INTC_INTMSKCLR1);
+		__raw_writel(0x40000000, INTC_INTMSKCLR1);
 		register_intc_controller(&intc_desc_irl4567);
 		break;
 	case IRQ_MODE_IRL3210_MASK:
 		/* enable IRL0-3 and mask using cpu intc controller */
-		ctrl_outl(0x80000000, INTC_INTMSKCLR1);
+		__raw_writel(0x80000000, INTC_INTMSKCLR1);
 		register_intc_controller(&intc_desc_irl0123);
 		break;
 	default:
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c
index 7167348..7e58532 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c
@@ -867,14 +867,14 @@
 void __init plat_irq_setup(void)
 {
 	/* disable IRQ3-0 + IRQ7-4 */
-	ctrl_outl(0xff000000, INTC_INTMSK0);
+	__raw_writel(0xff000000, INTC_INTMSK0);
 
 	/* disable IRL3-0 + IRL7-4 */
-	ctrl_outl(0xc0000000, INTC_INTMSK1);
-	ctrl_outl(0xfffefffe, INTC_INTMSK2);
+	__raw_writel(0xc0000000, INTC_INTMSK1);
+	__raw_writel(0xfffefffe, INTC_INTMSK2);
 
 	/* select IRL mode for IRL3-0 + IRL7-4 */
-	ctrl_outl(ctrl_inl(INTC_ICR0) & ~0x00c00000, INTC_ICR0);
+	__raw_writel(__raw_readl(INTC_ICR0) & ~0x00c00000, INTC_ICR0);
 
 	register_intc_controller(&intc_desc);
 }
@@ -884,32 +884,32 @@
 	switch (mode) {
 	case IRQ_MODE_IRQ7654:
 		/* select IRQ mode for IRL7-4 */
-		ctrl_outl(ctrl_inl(INTC_ICR0) | 0x00400000, INTC_ICR0);
+		__raw_writel(__raw_readl(INTC_ICR0) | 0x00400000, INTC_ICR0);
 		register_intc_controller(&intc_desc_irq4567);
 		break;
 	case IRQ_MODE_IRQ3210:
 		/* select IRQ mode for IRL3-0 */
-		ctrl_outl(ctrl_inl(INTC_ICR0) | 0x00800000, INTC_ICR0);
+		__raw_writel(__raw_readl(INTC_ICR0) | 0x00800000, INTC_ICR0);
 		register_intc_controller(&intc_desc_irq0123);
 		break;
 	case IRQ_MODE_IRL7654:
 		/* enable IRL7-4 but don't provide any masking */
-		ctrl_outl(0x40000000, INTC_INTMSKCLR1);
-		ctrl_outl(0x0000fffe, INTC_INTMSKCLR2);
+		__raw_writel(0x40000000, INTC_INTMSKCLR1);
+		__raw_writel(0x0000fffe, INTC_INTMSKCLR2);
 		break;
 	case IRQ_MODE_IRL3210:
 		/* enable IRL0-3 but don't provide any masking */
-		ctrl_outl(0x80000000, INTC_INTMSKCLR1);
-		ctrl_outl(0xfffe0000, INTC_INTMSKCLR2);
+		__raw_writel(0x80000000, INTC_INTMSKCLR1);
+		__raw_writel(0xfffe0000, INTC_INTMSKCLR2);
 		break;
 	case IRQ_MODE_IRL7654_MASK:
 		/* enable IRL7-4 and mask using cpu intc controller */
-		ctrl_outl(0x40000000, INTC_INTMSKCLR1);
+		__raw_writel(0x40000000, INTC_INTMSKCLR1);
 		register_intc_controller(&intc_desc_irl4567);
 		break;
 	case IRQ_MODE_IRL3210_MASK:
 		/* enable IRL0-3 and mask using cpu intc controller */
-		ctrl_outl(0x80000000, INTC_INTMSKCLR1);
+		__raw_writel(0x80000000, INTC_INTMSKCLR1);
 		register_intc_controller(&intc_desc_irl0123);
 		break;
 	default:
diff --git a/arch/sh/kernel/cpu/sh4a/smp-shx3.c b/arch/sh/kernel/cpu/sh4a/smp-shx3.c
index 5863e0c..11bf4c1 100644
--- a/arch/sh/kernel/cpu/sh4a/smp-shx3.c
+++ b/arch/sh/kernel/cpu/sh4a/smp-shx3.c
@@ -78,7 +78,10 @@
 
 void plat_start_cpu(unsigned int cpu, unsigned long entry_point)
 {
-	__raw_writel(entry_point, RESET_REG(cpu));
+	if (__in_29bit_mode())
+		__raw_writel(entry_point, RESET_REG(cpu));
+	else
+		__raw_writel(virt_to_phys(entry_point), RESET_REG(cpu));
 
 	if (!(__raw_readl(STBCR_REG(cpu)) & STBCR_MSTP))
 		__raw_writel(STBCR_MSTP, STBCR_REG(cpu));
diff --git a/arch/sh/kernel/cpu/sh4a/ubc.c b/arch/sh/kernel/cpu/sh4a/ubc.c
new file mode 100644
index 0000000..efb2745
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/ubc.c
@@ -0,0 +1,133 @@
+/*
+ * arch/sh/kernel/cpu/sh4a/ubc.c
+ *
+ * On-chip UBC support for SH-4A CPUs.
+ *
+ * Copyright (C) 2009 - 2010  Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <asm/hw_breakpoint.h>
+
+#define UBC_CBR(idx)	(0xff200000 + (0x20 * idx))
+#define UBC_CRR(idx)	(0xff200004 + (0x20 * idx))
+#define UBC_CAR(idx)	(0xff200008 + (0x20 * idx))
+#define UBC_CAMR(idx)	(0xff20000c + (0x20 * idx))
+
+#define UBC_CCMFR	0xff200600
+#define UBC_CBCR	0xff200620
+
+/* CRR */
+#define UBC_CRR_PCB	(1 << 1)
+#define UBC_CRR_BIE	(1 << 0)
+
+/* CBR */
+#define UBC_CBR_CE	(1 << 0)
+
+static struct sh_ubc sh4a_ubc;
+
+static void sh4a_ubc_enable(struct arch_hw_breakpoint *info, int idx)
+{
+	__raw_writel(UBC_CBR_CE | info->len | info->type, UBC_CBR(idx));
+	__raw_writel(info->address, UBC_CAR(idx));
+}
+
+static void sh4a_ubc_disable(struct arch_hw_breakpoint *info, int idx)
+{
+	__raw_writel(0, UBC_CBR(idx));
+	__raw_writel(0, UBC_CAR(idx));
+}
+
+static void sh4a_ubc_enable_all(unsigned long mask)
+{
+	int i;
+
+	for (i = 0; i < sh4a_ubc.num_events; i++)
+		if (mask & (1 << i))
+			__raw_writel(__raw_readl(UBC_CBR(i)) | UBC_CBR_CE,
+				     UBC_CBR(i));
+}
+
+static void sh4a_ubc_disable_all(void)
+{
+	int i;
+
+	for (i = 0; i < sh4a_ubc.num_events; i++)
+		__raw_writel(__raw_readl(UBC_CBR(i)) & ~UBC_CBR_CE,
+			     UBC_CBR(i));
+}
+
+static unsigned long sh4a_ubc_active_mask(void)
+{
+	unsigned long active = 0;
+	int i;
+
+	for (i = 0; i < sh4a_ubc.num_events; i++)
+		if (__raw_readl(UBC_CBR(i)) & UBC_CBR_CE)
+			active |= (1 << i);
+
+	return active;
+}
+
+static unsigned long sh4a_ubc_triggered_mask(void)
+{
+	return __raw_readl(UBC_CCMFR);
+}
+
+static void sh4a_ubc_clear_triggered_mask(unsigned long mask)
+{
+	__raw_writel(__raw_readl(UBC_CCMFR) & ~mask, UBC_CCMFR);
+}
+
+static struct sh_ubc sh4a_ubc = {
+	.name			= "SH-4A",
+	.num_events		= 2,
+	.trap_nr		= 0x1e0,
+	.enable			= sh4a_ubc_enable,
+	.disable		= sh4a_ubc_disable,
+	.enable_all		= sh4a_ubc_enable_all,
+	.disable_all		= sh4a_ubc_disable_all,
+	.active_mask		= sh4a_ubc_active_mask,
+	.triggered_mask		= sh4a_ubc_triggered_mask,
+	.clear_triggered_mask	= sh4a_ubc_clear_triggered_mask,
+};
+
+static int __init sh4a_ubc_init(void)
+{
+	struct clk *ubc_iclk = clk_get(NULL, "ubc0");
+	int i;
+
+	/*
+	 * The UBC MSTP bit is optional, as not all platforms will have
+	 * it. Just ignore it if we can't find it.
+	 */
+	if (IS_ERR(ubc_iclk))
+		ubc_iclk = NULL;
+
+	clk_enable(ubc_iclk);
+
+	__raw_writel(0, UBC_CBCR);
+
+	for (i = 0; i < sh4a_ubc.num_events; i++) {
+		__raw_writel(0, UBC_CAMR(i));
+		__raw_writel(0, UBC_CBR(i));
+
+		__raw_writel(UBC_CRR_BIE | UBC_CRR_PCB, UBC_CRR(i));
+
+		/* dummy read for write posting */
+		(void)__raw_readl(UBC_CRR(i));
+	}
+
+	clk_disable(ubc_iclk);
+
+	sh4a_ubc.clk = ubc_iclk;
+
+	return register_sh_ubc(&sh4a_ubc);
+}
+arch_initcall(sh4a_ubc_init);
diff --git a/arch/sh/kernel/cpu/sh5/clock-sh5.c b/arch/sh/kernel/cpu/sh5/clock-sh5.c
index 7f864eb..9cfc19b 100644
--- a/arch/sh/kernel/cpu/sh5/clock-sh5.c
+++ b/arch/sh/kernel/cpu/sh5/clock-sh5.c
@@ -24,7 +24,7 @@
 
 static void master_clk_init(struct clk *clk)
 {
-	int idx = (ctrl_inl(cprc_base + 0x00) >> 6) & 0x0007;
+	int idx = (__raw_readl(cprc_base + 0x00) >> 6) & 0x0007;
 	clk->rate *= ifc_table[idx];
 }
 
@@ -34,7 +34,7 @@
 
 static unsigned long module_clk_recalc(struct clk *clk)
 {
-	int idx = (ctrl_inw(cprc_base) >> 12) & 0x0007;
+	int idx = (__raw_readw(cprc_base) >> 12) & 0x0007;
 	return clk->parent->rate / ifc_table[idx];
 }
 
@@ -44,7 +44,7 @@
 
 static unsigned long bus_clk_recalc(struct clk *clk)
 {
-	int idx = (ctrl_inw(cprc_base) >> 3) & 0x0007;
+	int idx = (__raw_readw(cprc_base) >> 3) & 0x0007;
 	return clk->parent->rate / ifc_table[idx];
 }
 
@@ -54,7 +54,7 @@
 
 static unsigned long cpu_clk_recalc(struct clk *clk)
 {
-	int idx = (ctrl_inw(cprc_base) & 0x0007);
+	int idx = (__raw_readw(cprc_base) & 0x0007);
 	return clk->parent->rate / ifc_table[idx];
 }
 
diff --git a/arch/sh/kernel/cpu/sh5/entry.S b/arch/sh/kernel/cpu/sh5/entry.S
index 8f13f73..6b80295 100644
--- a/arch/sh/kernel/cpu/sh5/entry.S
+++ b/arch/sh/kernel/cpu/sh5/entry.S
@@ -187,7 +187,7 @@
 	.rept 6
 		.long do_exception_error	/* 0x880 - 0x920 */
 	.endr
-	.long	do_software_break_point	/* 0x940 */
+	.long	breakpoint_trap_handler	/* 0x940 */
 	.long	do_exception_error		/* 0x960 */
 	.long	do_single_step		/* 0x980 */
 
@@ -1124,7 +1124,7 @@
 	pta	its_IRQ, tr0
 	beqi/l	r4, EVENT_INTERRUPT, tr0
 #ifdef CONFIG_SH_FPU
-	movi	do_fpu_state_restore, r6
+	movi	fpu_state_restore_trap_handler, r6
 #else
 	movi	do_exception_error, r6
 #endif
@@ -1135,7 +1135,7 @@
 	pta	its_IRQ, tr0
 	beqi/l	r4, EVENT_INTERRUPT, tr0
 #ifdef CONFIG_SH_FPU
-	movi	do_fpu_state_restore, r6
+	movi	fpu_state_restore_trap_handler, r6
 #else
 	movi	do_exception_error, r6
 #endif
diff --git a/arch/sh/kernel/cpu/sh5/fpu.c b/arch/sh/kernel/cpu/sh5/fpu.c
index 4648cce..4b3bb35 100644
--- a/arch/sh/kernel/cpu/sh5/fpu.c
+++ b/arch/sh/kernel/cpu/sh5/fpu.c
@@ -15,24 +15,6 @@
 #include <linux/sched.h>
 #include <linux/signal.h>
 #include <asm/processor.h>
-#include <asm/user.h>
-#include <asm/io.h>
-#include <asm/fpu.h>
-
-/*
- * Initially load the FPU with signalling NANS.  This bit pattern
- * has the property that no matter whether considered as single or as
- * double precision, it still represents a signalling NAN.
- */
-#define sNAN64		0xFFFFFFFFFFFFFFFFULL
-#define sNAN32		0xFFFFFFFFUL
-
-static union sh_fpu_union init_fpuregs = {
-	.hard = {
-		.fp_regs = { [0 ... 63] = sNAN32 },
-		.fpscr = FPSCR_INIT
-	}
-};
 
 void save_fpu(struct task_struct *tsk)
 {
@@ -72,12 +54,11 @@
 		     "fgetscr   fr63\n\t"
 		     "fst.s     %0, (32*8), fr63\n\t"
 		: /* no output */
-		: "r" (&tsk->thread.fpu.hard)
+		: "r" (&tsk->thread.xstate->hardfpu)
 		: "memory");
 }
 
-static inline void
-fpload(struct sh_fpu_hard_struct *fpregs)
+void restore_fpu(struct task_struct *tsk)
 {
 	asm volatile("fld.p     %0, (0*8), fp0\n\t"
 		     "fld.p     %0, (1*8), fp2\n\t"
@@ -116,16 +97,11 @@
 
 		     "fld.p     %0, (31*8), fp62\n\t"
 		: /* no output */
-		: "r" (fpregs) );
+		: "r" (&tsk->thread.xstate->hardfpu)
+		: "memory");
 }
 
-void fpinit(struct sh_fpu_hard_struct *fpregs)
-{
-	*fpregs = init_fpuregs.hard;
-}
-
-asmlinkage void
-do_fpu_error(unsigned long ex, struct pt_regs *regs)
+asmlinkage void do_fpu_error(unsigned long ex, struct pt_regs *regs)
 {
 	struct task_struct *tsk = current;
 
@@ -133,35 +109,6 @@
 
 	tsk->thread.trap_no = 11;
 	tsk->thread.error_code = 0;
+
 	force_sig(SIGFPE, tsk);
 }
-
-
-asmlinkage void
-do_fpu_state_restore(unsigned long ex, struct pt_regs *regs)
-{
-	void die(const char *str, struct pt_regs *regs, long err);
-
-	if (! user_mode(regs))
-		die("FPU used in kernel", regs, ex);
-
-	regs->sr &= ~SR_FD;
-
-	if (last_task_used_math == current)
-		return;
-
-	enable_fpu();
-	if (last_task_used_math != NULL)
-		/* Other processes fpu state, save away */
-		save_fpu(last_task_used_math);
-
-        last_task_used_math = current;
-        if (used_math()) {
-                fpload(&current->thread.fpu.hard);
-        } else {
-		/* First time FPU user.  */
-		fpload(&init_fpuregs.hard);
-                set_used_math();
-        }
-	disable_fpu();
-}
diff --git a/arch/sh/kernel/cpu/shmobile/pm.c b/arch/sh/kernel/cpu/shmobile/pm.c
index ca029a4..e559687 100644
--- a/arch/sh/kernel/cpu/shmobile/pm.c
+++ b/arch/sh/kernel/cpu/shmobile/pm.c
@@ -33,7 +33,8 @@
 #define SUSP_MODE_SLEEP		(SUSP_SH_SLEEP)
 #define SUSP_MODE_SLEEP_SF	(SUSP_SH_SLEEP | SUSP_SH_SF)
 #define SUSP_MODE_STANDBY_SF	(SUSP_SH_STANDBY | SUSP_SH_SF)
-#define SUSP_MODE_RSTANDBY	(SUSP_SH_RSTANDBY | SUSP_SH_MMU | SUSP_SH_SF)
+#define SUSP_MODE_RSTANDBY_SF \
+	(SUSP_SH_RSTANDBY | SUSP_SH_MMU | SUSP_SH_REGS | SUSP_SH_SF)
  /*
   * U-standby mode is unsupported since it needs bootloader hacks
   */
diff --git a/arch/sh/kernel/cpu/shmobile/sleep.S b/arch/sh/kernel/cpu/shmobile/sleep.S
index e9dd7fa..e6aac65 100644
--- a/arch/sh/kernel/cpu/shmobile/sleep.S
+++ b/arch/sh/kernel/cpu/shmobile/sleep.S
@@ -48,8 +48,48 @@
 	stc	sr, r0
 	mov.l	r0, @(SH_SLEEP_SR, r5)
 
-	/* save sp */
+	/* save general purpose registers to stack if needed */
+	mov.l	@(SH_SLEEP_MODE, r5), r0
+	tst	#SUSP_SH_REGS, r0
+	bt	skip_regs_save
+
+	sts.l	pr, @-r15
+	mov.l	r14, @-r15
+	mov.l	r13, @-r15
+	mov.l	r12, @-r15
+	mov.l	r11, @-r15
+	mov.l	r10, @-r15
+	mov.l	r9, @-r15
+	mov.l	r8, @-r15
+
+	/* make sure bank0 is selected, save low registers */
+	mov.l	rb_bit, r9
+	not	r9, r9
+	bsr	set_sr
+	 mov	#0, r10
+
+	bsr	save_low_regs
+	 nop
+
+	/* switch to bank 1, save low registers */
+	mov.l	rb_bit, r10
+	bsr	set_sr
+	 mov	#-1, r9
+
+	bsr	save_low_regs
+	 nop
+
+	/* switch back to bank 0 */
+	mov.l	rb_bit, r9
+	not	r9, r9
+	bsr	set_sr
+	 mov	#0, r10
+
+skip_regs_save:
+
+	/* save sp, also set to internal ram */
 	mov.l	r15, @(SH_SLEEP_SP, r5)
+	mov	r5, r15
 
 	/* save stbcr */
 	bsr     save_register
@@ -60,7 +100,7 @@
 	tst	#SUSP_SH_MMU, r0
 	bt	skip_mmu_save_disable
 
-       /* save mmu state */
+	/* save mmu state */
 	bsr	save_register
 	 mov	#SH_SLEEP_REG_PTEH, r0
 
@@ -177,6 +217,29 @@
 	mov.l	@(r0, r5), r0
 	rts
 	 nop
+
+set_sr:
+	stc	sr, r8
+	and	r9, r8
+	or	r10, r8
+	ldc	r8, sr
+	rts
+	 nop
+
+save_low_regs:
+	mov.l	r7, @-r15
+	mov.l	r6, @-r15
+	mov.l	r5, @-r15
+	mov.l	r4, @-r15
+	mov.l	r3, @-r15
+	mov.l	r2, @-r15
+	mov.l	r1, @-r15
+	rts
+	 mov.l	r0, @-r15
+
+	.balign 4
+rb_bit:	.long	0x20000000 ! RB=1
+
 ENTRY(sh_mobile_sleep_enter_end)
 
 	.balign 4
@@ -270,6 +333,40 @@
 	icbi	@r0
 
 skip_restore_mmu:
+
+	/* restore general purpose registers if needed */
+	mov.l	@(SH_SLEEP_MODE, r5), r0
+	tst	#SUSP_SH_REGS, r0
+	bt	skip_restore_regs
+
+	/* switch to bank 1, restore low registers */
+	mov.l	_rb_bit, r10
+	bsr	_set_sr
+	 mov	#-1, r9
+
+	bsr	restore_low_regs
+	 nop
+
+	/* switch to bank0, restore low registers */
+	mov.l	_rb_bit, r9
+	not	r9, r9
+	bsr	_set_sr
+	 mov	#0, r10
+
+	bsr	restore_low_regs
+	 nop
+
+	/* restore the rest of the registers */
+	mov.l	@r15+, r8
+	mov.l	@r15+, r9
+	mov.l	@r15+, r10
+	mov.l	@r15+, r11
+	mov.l	@r15+, r12
+	mov.l	@r15+, r13
+	mov.l	@r15+, r14
+	lds.l	@r15+, pr
+
+skip_restore_regs:
 	rte
 	 nop
 
@@ -283,6 +380,26 @@
 	rts
 	 nop
 
+_set_sr:
+	stc	sr, r8
+	and	r9, r8
+	or	r10, r8
+	ldc	r8, sr
+	rts
+	 nop
+
+restore_low_regs:
+	mov.l	@r15+, r0
+	mov.l	@r15+, r1
+	mov.l	@r15+, r2
+	mov.l	@r15+, r3
+	mov.l	@r15+, r4
+	mov.l	@r15+, r5
+	mov.l	@r15+, r6
+	rts
+	 mov.l	@r15+, r7
+
 	.balign 4
+_rb_bit:	.long	0x20000000 ! RB=1
 1:	.long	~0x7ff
 ENTRY(sh_mobile_sleep_resume_end)
diff --git a/arch/sh/kernel/debugtraps.S b/arch/sh/kernel/debugtraps.S
index 5917413..7a1b46f 100644
--- a/arch/sh/kernel/debugtraps.S
+++ b/arch/sh/kernel/debugtraps.S
@@ -13,7 +13,6 @@
 #include <linux/linkage.h>
 
 #if !defined(CONFIG_KGDB)
-#define breakpoint_trap_handler		debug_trap_handler
 #define singlestep_trap_handler		debug_trap_handler
 #endif
 
diff --git a/arch/sh/kernel/dwarf.c b/arch/sh/kernel/dwarf.c
index e511680..bd1c497 100644
--- a/arch/sh/kernel/dwarf.c
+++ b/arch/sh/kernel/dwarf.c
@@ -39,10 +39,10 @@
 static struct kmem_cache *dwarf_reg_cachep;
 static mempool_t *dwarf_reg_pool;
 
-static LIST_HEAD(dwarf_cie_list);
+static struct rb_root cie_root;
 static DEFINE_SPINLOCK(dwarf_cie_lock);
 
-static LIST_HEAD(dwarf_fde_list);
+static struct rb_root fde_root;
 static DEFINE_SPINLOCK(dwarf_fde_lock);
 
 static struct dwarf_cie *cached_cie;
@@ -301,7 +301,8 @@
  */
 static struct dwarf_cie *dwarf_lookup_cie(unsigned long cie_ptr)
 {
-	struct dwarf_cie *cie;
+	struct rb_node **rb_node = &cie_root.rb_node;
+	struct dwarf_cie *cie = NULL;
 	unsigned long flags;
 
 	spin_lock_irqsave(&dwarf_cie_lock, flags);
@@ -315,16 +316,24 @@
 		goto out;
 	}
 
-	list_for_each_entry(cie, &dwarf_cie_list, link) {
-		if (cie->cie_pointer == cie_ptr) {
-			cached_cie = cie;
-			break;
+	while (*rb_node) {
+		struct dwarf_cie *cie_tmp;
+
+		cie_tmp = rb_entry(*rb_node, struct dwarf_cie, node);
+		BUG_ON(!cie_tmp);
+
+		if (cie_ptr == cie_tmp->cie_pointer) {
+			cie = cie_tmp;
+			cached_cie = cie_tmp;
+			goto out;
+		} else {
+			if (cie_ptr < cie_tmp->cie_pointer)
+				rb_node = &(*rb_node)->rb_left;
+			else
+				rb_node = &(*rb_node)->rb_right;
 		}
 	}
 
-	/* 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;
@@ -336,25 +345,34 @@
  */
 struct dwarf_fde *dwarf_lookup_fde(unsigned long pc)
 {
-	struct dwarf_fde *fde;
+	struct rb_node **rb_node = &fde_root.rb_node;
+	struct dwarf_fde *fde = NULL;
 	unsigned long flags;
 
 	spin_lock_irqsave(&dwarf_fde_lock, flags);
 
-	list_for_each_entry(fde, &dwarf_fde_list, link) {
-		unsigned long start, end;
+	while (*rb_node) {
+		struct dwarf_fde *fde_tmp;
+		unsigned long tmp_start, tmp_end;
 
-		start = fde->initial_location;
-		end = fde->initial_location + fde->address_range;
+		fde_tmp = rb_entry(*rb_node, struct dwarf_fde, node);
+		BUG_ON(!fde_tmp);
 
-		if (pc >= start && pc < end)
-			break;
+		tmp_start = fde_tmp->initial_location;
+		tmp_end = fde_tmp->initial_location + fde_tmp->address_range;
+
+		if (pc < tmp_start) {
+			rb_node = &(*rb_node)->rb_left;
+		} else {
+			if (pc < tmp_end) {
+				fde = fde_tmp;
+				goto out;
+			} else
+				rb_node = &(*rb_node)->rb_right;
+		}
 	}
 
-	/* Couldn't find the entry in the list. */
-	if (&fde->link == &dwarf_fde_list)
-		fde = NULL;
-
+out:
 	spin_unlock_irqrestore(&dwarf_fde_lock, flags);
 
 	return fde;
@@ -552,8 +570,8 @@
  *	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 *dwarf_unwind_stack(unsigned long pc,
+				       struct dwarf_frame *prev)
 {
 	struct dwarf_frame *frame;
 	struct dwarf_cie *cie;
@@ -708,6 +726,8 @@
 static int dwarf_parse_cie(void *entry, void *p, unsigned long len,
 			   unsigned char *end, struct module *mod)
 {
+	struct rb_node **rb_node = &cie_root.rb_node;
+	struct rb_node *parent;
 	struct dwarf_cie *cie;
 	unsigned long flags;
 	int count;
@@ -802,11 +822,30 @@
 	cie->initial_instructions = p;
 	cie->instructions_end = end;
 
-	cie->mod = mod;
-
 	/* Add to list */
 	spin_lock_irqsave(&dwarf_cie_lock, flags);
-	list_add_tail(&cie->link, &dwarf_cie_list);
+
+	while (*rb_node) {
+		struct dwarf_cie *cie_tmp;
+
+		cie_tmp = rb_entry(*rb_node, struct dwarf_cie, node);
+
+		parent = *rb_node;
+
+		if (cie->cie_pointer < cie_tmp->cie_pointer)
+			rb_node = &parent->rb_left;
+		else if (cie->cie_pointer >= cie_tmp->cie_pointer)
+			rb_node = &parent->rb_right;
+		else
+			WARN_ON(1);
+	}
+
+	rb_link_node(&cie->node, parent, rb_node);
+	rb_insert_color(&cie->node, &cie_root);
+
+	if (mod != NULL)
+		list_add_tail(&cie->link, &mod->arch.cie_list);
+
 	spin_unlock_irqrestore(&dwarf_cie_lock, flags);
 
 	return 0;
@@ -816,6 +855,8 @@
 			   void *start, unsigned long len,
 			   unsigned char *end, struct module *mod)
 {
+	struct rb_node **rb_node = &fde_root.rb_node;
+	struct rb_node *parent;
 	struct dwarf_fde *fde;
 	struct dwarf_cie *cie;
 	unsigned long flags;
@@ -863,11 +904,38 @@
 	fde->instructions = p;
 	fde->end = end;
 
-	fde->mod = mod;
-
 	/* Add to list. */
 	spin_lock_irqsave(&dwarf_fde_lock, flags);
-	list_add_tail(&fde->link, &dwarf_fde_list);
+
+	while (*rb_node) {
+		struct dwarf_fde *fde_tmp;
+		unsigned long tmp_start, tmp_end;
+		unsigned long start, end;
+
+		fde_tmp = rb_entry(*rb_node, struct dwarf_fde, node);
+
+		start = fde->initial_location;
+		end = fde->initial_location + fde->address_range;
+
+		tmp_start = fde_tmp->initial_location;
+		tmp_end = fde_tmp->initial_location + fde_tmp->address_range;
+
+		parent = *rb_node;
+
+		if (start < tmp_start)
+			rb_node = &parent->rb_left;
+		else if (start >= tmp_end)
+			rb_node = &parent->rb_right;
+		else
+			WARN_ON(1);
+	}
+
+	rb_link_node(&fde->node, parent, rb_node);
+	rb_insert_color(&fde->node, &fde_root);
+
+	if (mod != NULL)
+		list_add_tail(&fde->link, &mod->arch.fde_list);
+
 	spin_unlock_irqrestore(&dwarf_fde_lock, flags);
 
 	return 0;
@@ -912,19 +980,29 @@
 
 static void dwarf_unwinder_cleanup(void)
 {
-	struct dwarf_cie *cie, *cie_tmp;
-	struct dwarf_fde *fde, *fde_tmp;
+	struct rb_node **fde_rb_node = &fde_root.rb_node;
+	struct rb_node **cie_rb_node = &cie_root.rb_node;
 
 	/*
 	 * 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.
 	 */
-	list_for_each_entry_safe(cie, cie_tmp, &dwarf_cie_list, link)
-		kfree(cie);
+	while (*fde_rb_node) {
+		struct dwarf_fde *fde;
 
-	list_for_each_entry_safe(fde, fde_tmp, &dwarf_fde_list, link)
+		fde = rb_entry(*fde_rb_node, struct dwarf_fde, node);
+		rb_erase(*fde_rb_node, &fde_root);
 		kfree(fde);
+	}
+
+	while (*cie_rb_node) {
+		struct dwarf_cie *cie;
+
+		cie = rb_entry(*cie_rb_node, struct dwarf_cie, node);
+		rb_erase(*cie_rb_node, &cie_root);
+		kfree(cie);
+	}
 
 	kmem_cache_destroy(dwarf_reg_cachep);
 	kmem_cache_destroy(dwarf_frame_cachep);
@@ -1024,6 +1102,8 @@
 
 	/* Did we find the .eh_frame section? */
 	if (i != hdr->e_shnum) {
+		INIT_LIST_HEAD(&me->arch.cie_list);
+		INIT_LIST_HEAD(&me->arch.fde_list);
 		err = dwarf_parse_section((char *)start, (char *)end, me);
 		if (err) {
 			printk(KERN_WARNING "%s: failed to parse DWARF info\n",
@@ -1044,38 +1124,26 @@
  */
 void module_dwarf_cleanup(struct module *mod)
 {
-	struct dwarf_fde *fde;
-	struct dwarf_cie *cie;
+	struct dwarf_fde *fde, *ftmp;
+	struct dwarf_cie *cie, *ctmp;
 	unsigned long flags;
 
 	spin_lock_irqsave(&dwarf_cie_lock, flags);
 
-again_cie:
-	list_for_each_entry(cie, &dwarf_cie_list, link) {
-		if (cie->mod == mod)
-			break;
-	}
-
-	if (&cie->link != &dwarf_cie_list) {
+	list_for_each_entry_safe(cie, ctmp, &mod->arch.cie_list, link) {
 		list_del(&cie->link);
+		rb_erase(&cie->node, &cie_root);
 		kfree(cie);
-		goto again_cie;
 	}
 
 	spin_unlock_irqrestore(&dwarf_cie_lock, flags);
 
 	spin_lock_irqsave(&dwarf_fde_lock, flags);
 
-again_fde:
-	list_for_each_entry(fde, &dwarf_fde_list, link) {
-		if (fde->mod == mod)
-			break;
-	}
-
-	if (&fde->link != &dwarf_fde_list) {
+	list_for_each_entry_safe(fde, ftmp, &mod->arch.fde_list, link) {
 		list_del(&fde->link);
+		rb_erase(&fde->node, &fde_root);
 		kfree(fde);
-		goto again_fde;
 	}
 
 	spin_unlock_irqrestore(&dwarf_fde_lock, flags);
@@ -1094,8 +1162,6 @@
 static int __init dwarf_unwinder_init(void)
 {
 	int err;
-	INIT_LIST_HEAD(&dwarf_cie_list);
-	INIT_LIST_HEAD(&dwarf_fde_list);
 
 	dwarf_frame_cachep = kmem_cache_create("dwarf_frames",
 			sizeof(struct dwarf_frame), 0,
diff --git a/arch/sh/kernel/early_printk.c b/arch/sh/kernel/early_printk.c
deleted file mode 100644
index f8bb50c..0000000
--- a/arch/sh/kernel/early_printk.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * arch/sh/kernel/early_printk.c
- *
- *  Copyright (C) 1999, 2000  Niibe Yutaka
- *  Copyright (C) 2002  M. R. Brown
- *  Copyright (C) 2004 - 2007  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-#include <linux/console.h>
-#include <linux/tty.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-
-#include <asm/sh_bios.h>
-
-/*
- *	Print a string through the BIOS
- */
-static void sh_console_write(struct console *co, const char *s,
-				 unsigned count)
-{
-	sh_bios_console_write(s, count);
-}
-
-/*
- *	Setup initial baud/bits/parity. We do two things here:
- *	- construct a cflag setting for the first rs_open()
- *	- initialize the serial port
- *	Return non-zero if we didn't find a serial port.
- */
-static int __init sh_console_setup(struct console *co, char *options)
-{
-	int	cflag = CREAD | HUPCL | CLOCAL;
-
-	/*
-	 *	Now construct a cflag setting.
-	 *	TODO: this is a totally bogus cflag, as we have
-	 *	no idea what serial settings the BIOS is using, or
-	 *	even if its using the serial port at all.
-	 */
-	cflag |= B115200 | CS8 | /*no parity*/0;
-
-	co->cflag = cflag;
-
-	return 0;
-}
-
-static struct console bios_console = {
-	.name		= "bios",
-	.write		= sh_console_write,
-	.setup		= sh_console_setup,
-	.flags		= CON_PRINTBUFFER,
-	.index		= -1,
-};
-
-static struct console *early_console;
-
-static int __init setup_early_printk(char *buf)
-{
-	int keep_early = 0;
-
-	if (!buf)
-		return 0;
-
-	if (strstr(buf, "keep"))
-		keep_early = 1;
-
-	if (!strncmp(buf, "bios", 4))
-		early_console = &bios_console;
-
-	if (likely(early_console)) {
-		if (keep_early)
-			early_console->flags &= ~CON_BOOT;
-		else
-			early_console->flags |= CON_BOOT;
-		register_console(early_console);
-	}
-
-	return 0;
-}
-early_param("earlyprintk", setup_early_printk);
diff --git a/arch/sh/kernel/head_32.S b/arch/sh/kernel/head_32.S
index 1151ecd..fe0b743 100644
--- a/arch/sh/kernel/head_32.S
+++ b/arch/sh/kernel/head_32.S
@@ -3,6 +3,7 @@
  *  arch/sh/kernel/head.S
  *
  *  Copyright (C) 1999, 2000  Niibe Yutaka & Kaz Kojima
+ *  Copyright (C) 2010  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
@@ -13,6 +14,8 @@
 #include <linux/init.h>
 #include <linux/linkage.h>
 #include <asm/thread_info.h>
+#include <asm/mmu.h>
+#include <cpu/mmu_context.h>
 
 #ifdef CONFIG_CPU_SH4A
 #define SYNCO()		synco
@@ -33,7 +36,7 @@
 	.long	1		/* LOADER_TYPE */
 	.long	0x00000000	/* INITRD_START */
 	.long	0x00000000	/* INITRD_SIZE */
-#if defined(CONFIG_32BIT) && defined(CONFIG_PMB_FIXED)
+#ifdef CONFIG_32BIT
 	.long	0x53453f00 + 32	/* "SE?" = 32 bit */
 #else
 	.long	0x53453f00 + 29	/* "SE?" = 29 bit */
@@ -82,6 +85,209 @@
 	ldc	r0, r7_bank	! ... and initial thread_info
 #endif
 
+#ifdef CONFIG_PMB
+/*
+ * Reconfigure the initial PMB mappings setup by the hardware.
+ *
+ * When we boot in 32-bit MMU mode there are 2 PMB entries already
+ * setup for us.
+ *
+ * Entry       VPN	   PPN	    V	SZ	C	UB	WT
+ * ---------------------------------------------------------------
+ *   0	    0x80000000 0x00000000   1  512MB	1	0	1
+ *   1	    0xA0000000 0x00000000   1  512MB	0	0	0
+ *
+ * But we reprogram them here because we want complete control over
+ * our address space and the initial mappings may not map PAGE_OFFSET
+ * to __MEMORY_START (or even map all of our RAM).
+ *
+ * Once we've setup cached and uncached mappings we clear the rest of the
+ * PMB entries. This clearing also deals with the fact that PMB entries
+ * can persist across reboots. The PMB could have been left in any state
+ * when the reboot occurred, so to be safe we clear all entries and start
+ * with with a clean slate.
+ *
+ * The uncached mapping is constructed using the smallest possible
+ * mapping with a single unbufferable page. Only the kernel text needs to
+ * be covered via the uncached mapping so that certain functions can be
+ * run uncached.
+ *
+ * Drivers and the like that have previously abused the 1:1 identity
+ * mapping are unsupported in 32-bit mode and must specify their caching
+ * preference when page tables are constructed.
+ *
+ * This frees up the P2 space for more nefarious purposes.
+ *
+ * Register utilization is as follows:
+ *
+ *	r0 = PMB_DATA data field
+ *	r1 = PMB_DATA address field
+ *	r2 = PMB_ADDR data field
+ *	r3 = PMB_ADDR address field
+ *	r4 = PMB_E_SHIFT
+ *	r5 = remaining amount of RAM to map
+ *	r6 = PMB mapping size we're trying to use
+ *	r7 = cached_to_uncached
+ *	r8 = scratch register
+ *	r9 = scratch register
+ *	r10 = number of PMB entries we've setup
+ */
+
+	mov.l	.LMMUCR, r1	/* Flush the TLB */
+	mov.l	@r1, r0
+	or	#MMUCR_TI, r0
+	mov.l	r0, @r1
+
+	mov.l	.LMEMORY_SIZE, r5
+
+	mov	#PMB_E_SHIFT, r0
+	mov	#0x1, r4
+	shld	r0, r4
+
+	mov.l	.LFIRST_DATA_ENTRY, r0
+	mov.l	.LPMB_DATA, r1
+	mov.l	.LFIRST_ADDR_ENTRY, r2
+	mov.l	.LPMB_ADDR, r3
+
+	/*
+	 * First we need to walk the PMB and figure out if there are any
+	 * existing mappings that match the initial mappings VPN/PPN.
+	 * If these have already been established by the bootloader, we
+	 * don't bother setting up new entries here, and let the late PMB
+	 * initialization take care of things instead.
+	 *
+	 * Note that we may need to coalesce and merge entries in order
+	 * to reclaim more available PMB slots, which is much more than
+	 * we want to do at this early stage.
+	 */
+	mov	#0, r10
+	mov	#NR_PMB_ENTRIES, r9
+
+	mov	r1, r7		/* temporary PMB_DATA iter */
+
+.Lvalidate_existing_mappings:
+
+	mov.l	@r7, r8
+	and	r0, r8
+	cmp/eq	r0, r8		/* Check for valid __MEMORY_START mappings */
+	bt	.Lpmb_done
+
+	add	#1, r10		/* Increment the loop counter */
+	cmp/eq	r9, r10
+	bf/s	.Lvalidate_existing_mappings
+	 add	r4, r7		/* Increment to the next PMB_DATA entry */
+
+	/*
+	 * If we've fallen through, continue with setting up the initial
+	 * mappings.
+	 */
+
+	mov	r5, r7		/* cached_to_uncached */
+	mov	#0, r10
+
+#ifdef CONFIG_UNCACHED_MAPPING
+	/*
+	 * Uncached mapping
+	 */
+	mov	#(PMB_SZ_16M >> 2), r9
+	shll2	r9
+
+	mov	#(PMB_UB >> 8), r8
+	shll8	r8
+
+	or	r0, r8
+	or	r9, r8
+	mov.l	r8, @r1
+	mov	r2, r8
+	add	r7, r8
+	mov.l	r8, @r3
+
+	add	r4, r1
+	add	r4, r3
+	add	#1, r10
+#endif
+
+/*
+ * Iterate over all of the available sizes from largest to
+ * smallest for constructing the cached mapping.
+ */
+#define __PMB_ITER_BY_SIZE(size)			\
+.L##size:						\
+	mov	#(size >> 4), r6;			\
+	shll16	r6;					\
+	shll8	r6;					\
+							\
+	cmp/hi	r5, r6;					\
+	bt	9999f;					\
+							\
+	mov	#(PMB_SZ_##size##M >> 2), r9;		\
+	shll2	r9;					\
+							\
+	/*						\
+	 * Cached mapping				\
+	 */						\
+	mov	#PMB_C, r8;				\
+	or	r0, r8;					\
+	or	r9, r8;					\
+	mov.l	r8, @r1;				\
+	mov.l	r2, @r3;				\
+							\
+	/* Increment to the next PMB_DATA entry */	\
+	add	r4, r1;					\
+	/* Increment to the next PMB_ADDR entry */	\
+	add	r4, r3;					\
+	/* Increment number of PMB entries */		\
+	add	#1, r10;				\
+							\
+	sub	r6, r5;					\
+	add	r6, r0;					\
+	add	r6, r2;					\
+							\
+	bra	.L##size;				\
+9999:
+
+	__PMB_ITER_BY_SIZE(512)
+	__PMB_ITER_BY_SIZE(128)
+	__PMB_ITER_BY_SIZE(64)
+	__PMB_ITER_BY_SIZE(16)
+
+#ifdef CONFIG_UNCACHED_MAPPING
+	/*
+	 * Now that we can access it, update cached_to_uncached and
+	 * uncached_size.
+	 */
+	mov.l	.Lcached_to_uncached, r0
+	mov.l	r7, @r0
+
+	mov.l	.Luncached_size, r0
+	mov	#1, r7
+	shll16	r7
+	shll8	r7
+	mov.l	r7, @r0
+#endif
+
+	/*
+	 * Clear the remaining PMB entries.
+	 *
+	 * r3 = entry to begin clearing from
+	 * r10 = number of entries we've setup so far
+	 */
+	mov	#0, r1
+	mov	#NR_PMB_ENTRIES, r0
+
+.Lagain:
+	mov.l	r1, @r3		/* Clear PMB_ADDR entry */
+	add	#1, r10		/* Increment the loop counter */
+	cmp/eq	r0, r10
+	bf/s	.Lagain
+	 add	r4, r3		/* Increment to the next PMB_ADDR entry */
+
+	mov.l	6f, r0
+	icbi	@r0
+
+.Lpmb_done:
+#endif /* CONFIG_PMB */
+
 #ifndef CONFIG_SH_NO_BSS_INIT
 	/*
 	 * Don't clear BSS if running on slow platforms such as an RTL simulation,
@@ -131,3 +337,16 @@
 5:	.long	start_kernel
 6:	.long	sh_cpu_init
 7:	.long	init_thread_union
+
+#ifdef CONFIG_PMB
+.LPMB_ADDR:		.long	PMB_ADDR
+.LPMB_DATA:		.long	PMB_DATA
+.LFIRST_ADDR_ENTRY:	.long	PAGE_OFFSET | PMB_V
+.LFIRST_DATA_ENTRY:	.long	__MEMORY_START | PMB_V
+.LMMUCR:		.long	MMUCR
+.LMEMORY_SIZE:		.long	__MEMORY_SIZE
+#ifdef CONFIG_UNCACHED_MAPPING
+.Lcached_to_uncached:	.long	cached_to_uncached
+.Luncached_size:	.long	uncached_size
+#endif
+#endif
diff --git a/arch/sh/kernel/head_64.S b/arch/sh/kernel/head_64.S
index 3ea7658..defd851 100644
--- a/arch/sh/kernel/head_64.S
+++ b/arch/sh/kernel/head_64.S
@@ -220,7 +220,6 @@
 	add.l	r22, r63, r22		/* Sign extend */
 	putcfg	r21, 0, r22		/* Set MMUDR[0].PTEH */
 
-#ifdef CONFIG_EARLY_PRINTK
 	/*
 	 * Setup a DTLB translation for SCIF phys.
 	 */
@@ -231,7 +230,6 @@
 	movi    0xfa03, r22	/* 0xfa030000, fixed SCIF virt */
 	shori   0x0003, r22
 	putcfg  r21, 0, r22	/* PTEH last */
-#endif
 
 	/*
 	 * Set cache behaviours.
diff --git a/arch/sh/kernel/hw_breakpoint.c b/arch/sh/kernel/hw_breakpoint.c
new file mode 100644
index 0000000..e2f1753
--- /dev/null
+++ b/arch/sh/kernel/hw_breakpoint.c
@@ -0,0 +1,463 @@
+/*
+ * arch/sh/kernel/hw_breakpoint.c
+ *
+ * Unified kernel/user-space hardware breakpoint facility for the on-chip UBC.
+ *
+ * Copyright (C) 2009 - 2010  Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/perf_event.h>
+#include <linux/hw_breakpoint.h>
+#include <linux/percpu.h>
+#include <linux/kallsyms.h>
+#include <linux/notifier.h>
+#include <linux/kprobes.h>
+#include <linux/kdebug.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <asm/hw_breakpoint.h>
+#include <asm/mmu_context.h>
+#include <asm/ptrace.h>
+
+/*
+ * Stores the breakpoints currently in use on each breakpoint address
+ * register for each cpus
+ */
+static DEFINE_PER_CPU(struct perf_event *, bp_per_reg[HBP_NUM]);
+
+/*
+ * A dummy placeholder for early accesses until the CPUs get a chance to
+ * register their UBCs later in the boot process.
+ */
+static struct sh_ubc ubc_dummy = { .num_events = 0 };
+
+static struct sh_ubc *sh_ubc __read_mostly = &ubc_dummy;
+
+/*
+ * Install a perf counter breakpoint.
+ *
+ * We seek a free UBC channel and use it for this breakpoint.
+ *
+ * Atomic: we hold the counter->ctx->lock and we only handle variables
+ * and registers local to this cpu.
+ */
+int arch_install_hw_breakpoint(struct perf_event *bp)
+{
+	struct arch_hw_breakpoint *info = counter_arch_bp(bp);
+	int i;
+
+	for (i = 0; i < sh_ubc->num_events; i++) {
+		struct perf_event **slot = &__get_cpu_var(bp_per_reg[i]);
+
+		if (!*slot) {
+			*slot = bp;
+			break;
+		}
+	}
+
+	if (WARN_ONCE(i == sh_ubc->num_events, "Can't find any breakpoint slot"))
+		return -EBUSY;
+
+	clk_enable(sh_ubc->clk);
+	sh_ubc->enable(info, i);
+
+	return 0;
+}
+
+/*
+ * Uninstall the breakpoint contained in the given counter.
+ *
+ * First we search the debug address register it uses and then we disable
+ * it.
+ *
+ * Atomic: we hold the counter->ctx->lock and we only handle variables
+ * and registers local to this cpu.
+ */
+void arch_uninstall_hw_breakpoint(struct perf_event *bp)
+{
+	struct arch_hw_breakpoint *info = counter_arch_bp(bp);
+	int i;
+
+	for (i = 0; i < sh_ubc->num_events; i++) {
+		struct perf_event **slot = &__get_cpu_var(bp_per_reg[i]);
+
+		if (*slot == bp) {
+			*slot = NULL;
+			break;
+		}
+	}
+
+	if (WARN_ONCE(i == sh_ubc->num_events, "Can't find any breakpoint slot"))
+		return;
+
+	sh_ubc->disable(info, i);
+	clk_disable(sh_ubc->clk);
+}
+
+static int get_hbp_len(u16 hbp_len)
+{
+	unsigned int len_in_bytes = 0;
+
+	switch (hbp_len) {
+	case SH_BREAKPOINT_LEN_1:
+		len_in_bytes = 1;
+		break;
+	case SH_BREAKPOINT_LEN_2:
+		len_in_bytes = 2;
+		break;
+	case SH_BREAKPOINT_LEN_4:
+		len_in_bytes = 4;
+		break;
+	case SH_BREAKPOINT_LEN_8:
+		len_in_bytes = 8;
+		break;
+	}
+	return len_in_bytes;
+}
+
+/*
+ * Check for virtual address in user space.
+ */
+int arch_check_va_in_userspace(unsigned long va, u16 hbp_len)
+{
+	unsigned int len;
+
+	len = get_hbp_len(hbp_len);
+
+	return (va <= TASK_SIZE - len);
+}
+
+/*
+ * Check for virtual address in kernel space.
+ */
+static int arch_check_va_in_kernelspace(unsigned long va, u8 hbp_len)
+{
+	unsigned int len;
+
+	len = get_hbp_len(hbp_len);
+
+	return (va >= TASK_SIZE) && ((va + len - 1) >= TASK_SIZE);
+}
+
+/*
+ * Store a breakpoint's encoded address, length, and type.
+ */
+static int arch_store_info(struct perf_event *bp)
+{
+	struct arch_hw_breakpoint *info = counter_arch_bp(bp);
+
+	/*
+	 * User-space requests will always have the address field populated
+	 * For kernel-addresses, either the address or symbol name can be
+	 * specified.
+	 */
+	if (info->name)
+		info->address = (unsigned long)kallsyms_lookup_name(info->name);
+	if (info->address)
+		return 0;
+
+	return -EINVAL;
+}
+
+int arch_bp_generic_fields(int sh_len, int sh_type,
+			   int *gen_len, int *gen_type)
+{
+	/* Len */
+	switch (sh_len) {
+	case SH_BREAKPOINT_LEN_1:
+		*gen_len = HW_BREAKPOINT_LEN_1;
+		break;
+	case SH_BREAKPOINT_LEN_2:
+		*gen_len = HW_BREAKPOINT_LEN_2;
+		break;
+	case SH_BREAKPOINT_LEN_4:
+		*gen_len = HW_BREAKPOINT_LEN_4;
+		break;
+	case SH_BREAKPOINT_LEN_8:
+		*gen_len = HW_BREAKPOINT_LEN_8;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* Type */
+	switch (sh_type) {
+	case SH_BREAKPOINT_READ:
+		*gen_type = HW_BREAKPOINT_R;
+	case SH_BREAKPOINT_WRITE:
+		*gen_type = HW_BREAKPOINT_W;
+		break;
+	case SH_BREAKPOINT_RW:
+		*gen_type = HW_BREAKPOINT_W | HW_BREAKPOINT_R;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int arch_build_bp_info(struct perf_event *bp)
+{
+	struct arch_hw_breakpoint *info = counter_arch_bp(bp);
+
+	info->address = bp->attr.bp_addr;
+
+	/* Len */
+	switch (bp->attr.bp_len) {
+	case HW_BREAKPOINT_LEN_1:
+		info->len = SH_BREAKPOINT_LEN_1;
+		break;
+	case HW_BREAKPOINT_LEN_2:
+		info->len = SH_BREAKPOINT_LEN_2;
+		break;
+	case HW_BREAKPOINT_LEN_4:
+		info->len = SH_BREAKPOINT_LEN_4;
+		break;
+	case HW_BREAKPOINT_LEN_8:
+		info->len = SH_BREAKPOINT_LEN_8;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* Type */
+	switch (bp->attr.bp_type) {
+	case HW_BREAKPOINT_R:
+		info->type = SH_BREAKPOINT_READ;
+		break;
+	case HW_BREAKPOINT_W:
+		info->type = SH_BREAKPOINT_WRITE;
+		break;
+	case HW_BREAKPOINT_W | HW_BREAKPOINT_R:
+		info->type = SH_BREAKPOINT_RW;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * Validate the arch-specific HW Breakpoint register settings
+ */
+int arch_validate_hwbkpt_settings(struct perf_event *bp,
+				  struct task_struct *tsk)
+{
+	struct arch_hw_breakpoint *info = counter_arch_bp(bp);
+	unsigned int align;
+	int ret;
+
+	ret = arch_build_bp_info(bp);
+	if (ret)
+		return ret;
+
+	ret = -EINVAL;
+
+	switch (info->len) {
+	case SH_BREAKPOINT_LEN_1:
+		align = 0;
+		break;
+	case SH_BREAKPOINT_LEN_2:
+		align = 1;
+		break;
+	case SH_BREAKPOINT_LEN_4:
+		align = 3;
+		break;
+	case SH_BREAKPOINT_LEN_8:
+		align = 7;
+		break;
+	default:
+		return ret;
+	}
+
+	ret = arch_store_info(bp);
+
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * Check that the low-order bits of the address are appropriate
+	 * for the alignment implied by len.
+	 */
+	if (info->address & align)
+		return -EINVAL;
+
+	/* Check that the virtual address is in the proper range */
+	if (tsk) {
+		if (!arch_check_va_in_userspace(info->address, info->len))
+			return -EFAULT;
+	} else {
+		if (!arch_check_va_in_kernelspace(info->address, info->len))
+			return -EFAULT;
+	}
+
+	return 0;
+}
+
+/*
+ * Release the user breakpoints used by ptrace
+ */
+void flush_ptrace_hw_breakpoint(struct task_struct *tsk)
+{
+	int i;
+	struct thread_struct *t = &tsk->thread;
+
+	for (i = 0; i < sh_ubc->num_events; i++) {
+		unregister_hw_breakpoint(t->ptrace_bps[i]);
+		t->ptrace_bps[i] = NULL;
+	}
+}
+
+static int __kprobes hw_breakpoint_handler(struct die_args *args)
+{
+	int cpu, i, rc = NOTIFY_STOP;
+	struct perf_event *bp;
+	unsigned int cmf, resume_mask;
+
+	/*
+	 * Do an early return if none of the channels triggered.
+	 */
+	cmf = sh_ubc->triggered_mask();
+	if (unlikely(!cmf))
+		return NOTIFY_DONE;
+
+	/*
+	 * By default, resume all of the active channels.
+	 */
+	resume_mask = sh_ubc->active_mask();
+
+	/*
+	 * Disable breakpoints during exception handling.
+	 */
+	sh_ubc->disable_all();
+
+	cpu = get_cpu();
+	for (i = 0; i < sh_ubc->num_events; i++) {
+		unsigned long event_mask = (1 << i);
+
+		if (likely(!(cmf & event_mask)))
+			continue;
+
+		/*
+		 * The counter may be concurrently released but that can only
+		 * occur from a call_rcu() path. We can then safely fetch
+		 * the breakpoint, use its callback, touch its counter
+		 * while we are in an rcu_read_lock() path.
+		 */
+		rcu_read_lock();
+
+		bp = per_cpu(bp_per_reg[i], cpu);
+		if (bp)
+			rc = NOTIFY_DONE;
+
+		/*
+		 * Reset the condition match flag to denote completion of
+		 * exception handling.
+		 */
+		sh_ubc->clear_triggered_mask(event_mask);
+
+		/*
+		 * bp can be NULL due to concurrent perf counter
+		 * removing.
+		 */
+		if (!bp) {
+			rcu_read_unlock();
+			break;
+		}
+
+		/*
+		 * Don't restore the channel if the breakpoint is from
+		 * ptrace, as it always operates in one-shot mode.
+		 */
+		if (bp->overflow_handler == ptrace_triggered)
+			resume_mask &= ~(1 << i);
+
+		perf_bp_event(bp, args->regs);
+
+		/* Deliver the signal to userspace */
+		if (arch_check_va_in_userspace(bp->attr.bp_addr,
+					       bp->attr.bp_len)) {
+			siginfo_t info;
+
+			info.si_signo = args->signr;
+			info.si_errno = notifier_to_errno(rc);
+			info.si_code = TRAP_HWBKPT;
+
+			force_sig_info(args->signr, &info, current);
+		}
+
+		rcu_read_unlock();
+	}
+
+	if (cmf == 0)
+		rc = NOTIFY_DONE;
+
+	sh_ubc->enable_all(resume_mask);
+
+	put_cpu();
+
+	return rc;
+}
+
+BUILD_TRAP_HANDLER(breakpoint)
+{
+	unsigned long ex = lookup_exception_vector();
+	TRAP_HANDLER_DECL;
+
+	notify_die(DIE_BREAKPOINT, "breakpoint", regs, 0, ex, SIGTRAP);
+}
+
+/*
+ * Handle debug exception notifications.
+ */
+int __kprobes hw_breakpoint_exceptions_notify(struct notifier_block *unused,
+				    unsigned long val, void *data)
+{
+	struct die_args *args = data;
+
+	if (val != DIE_BREAKPOINT)
+		return NOTIFY_DONE;
+
+	/*
+	 * If the breakpoint hasn't been triggered by the UBC, it's
+	 * probably from a debugger, so don't do anything more here.
+	 *
+	 * This also permits the UBC interface clock to remain off for
+	 * non-UBC breakpoints, as we don't need to check the triggered
+	 * or active channel masks.
+	 */
+	if (args->trapnr != sh_ubc->trap_nr)
+		return NOTIFY_DONE;
+
+	return hw_breakpoint_handler(data);
+}
+
+void hw_breakpoint_pmu_read(struct perf_event *bp)
+{
+	/* TODO */
+}
+
+void hw_breakpoint_pmu_unthrottle(struct perf_event *bp)
+{
+	/* TODO */
+}
+
+int register_sh_ubc(struct sh_ubc *ubc)
+{
+	/* Bail if it's already assigned */
+	if (sh_ubc != &ubc_dummy)
+		return -EBUSY;
+	sh_ubc = ubc;
+
+	pr_info("HW Breakpoints: %s UBC support registered\n", ubc->name);
+
+	WARN_ON(ubc->num_events > HBP_NUM);
+
+	return 0;
+}
diff --git a/arch/sh/kernel/idle.c b/arch/sh/kernel/idle.c
index 6b3d706..0fd7b41 100644
--- a/arch/sh/kernel/idle.c
+++ b/arch/sh/kernel/idle.c
@@ -20,10 +20,9 @@
 #include <asm/system.h>
 #include <asm/atomic.h>
 
-static int hlt_counter;
 void (*pm_idle)(void) = NULL;
-void (*pm_power_off)(void);
-EXPORT_SYMBOL(pm_power_off);
+
+static int hlt_counter;
 
 static int __init nohlt_setup(char *__unused)
 {
@@ -131,6 +130,15 @@
 {
 }
 
+void stop_this_cpu(void *unused)
+{
+	local_irq_disable();
+	cpu_clear(smp_processor_id(), cpu_online_map);
+
+	for (;;)
+		cpu_sleep();
+}
+
 /*
  * cpu_idle_wait - Used to ensure that all the CPUs discard old value of
  * pm_idle and update to new pm_idle value. Required while changing pm_idle
diff --git a/arch/sh/kernel/io_trapped.c b/arch/sh/kernel/io_trapped.c
index 69be603..4a8bb4e 100644
--- a/arch/sh/kernel/io_trapped.c
+++ b/arch/sh/kernel/io_trapped.c
@@ -184,31 +184,31 @@
 
 	switch (src_len) {
 	case 1:
-		tmp = ctrl_inb(src_addr);
+		tmp = __raw_readb(src_addr);
 		break;
 	case 2:
-		tmp = ctrl_inw(src_addr);
+		tmp = __raw_readw(src_addr);
 		break;
 	case 4:
-		tmp = ctrl_inl(src_addr);
+		tmp = __raw_readl(src_addr);
 		break;
 	case 8:
-		tmp = ctrl_inq(src_addr);
+		tmp = __raw_readq(src_addr);
 		break;
 	}
 
 	switch (dst_len) {
 	case 1:
-		ctrl_outb(tmp, dst_addr);
+		__raw_writeb(tmp, dst_addr);
 		break;
 	case 2:
-		ctrl_outw(tmp, dst_addr);
+		__raw_writew(tmp, dst_addr);
 		break;
 	case 4:
-		ctrl_outl(tmp, dst_addr);
+		__raw_writel(tmp, dst_addr);
 		break;
 	case 8:
-		ctrl_outq(tmp, dst_addr);
+		__raw_writeq(tmp, dst_addr);
 		break;
 	}
 
@@ -271,6 +271,8 @@
 	insn_size_t instruction;
 	int tmp;
 
+	if (trapped_io_disable)
+		return 0;
 	if (!lookup_tiop(address))
 		return 0;
 
diff --git a/arch/sh/kernel/kgdb.c b/arch/sh/kernel/kgdb.c
index 3e532d0..70c6965 100644
--- a/arch/sh/kernel/kgdb.c
+++ b/arch/sh/kernel/kgdb.c
@@ -1,7 +1,7 @@
 /*
  * SuperH KGDB support
  *
- * Copyright (C) 2008  Paul Mundt
+ * Copyright (C) 2008 - 2009  Paul Mundt
  *
  * Single stepping taken from the old stub by Henry Bell and Jeremy Siegel.
  *
@@ -251,24 +251,60 @@
 	local_irq_restore(flags);
 }
 
+static int __kgdb_notify(struct die_args *args, unsigned long cmd)
+{
+	int ret;
 
-BUILD_TRAP_HANDLER(breakpoint)
+	switch (cmd) {
+	case DIE_BREAKPOINT:
+		/*
+		 * This means a user thread is single stepping
+		 * a system call which should be ignored
+		 */
+		if (test_thread_flag(TIF_SINGLESTEP))
+			return NOTIFY_DONE;
+
+		ret = kgdb_handle_exception(args->trapnr & 0xff, args->signr,
+					    args->err, args->regs);
+		if (ret)
+			return NOTIFY_DONE;
+
+		break;
+	}
+
+	return NOTIFY_STOP;
+}
+
+static int
+kgdb_notify(struct notifier_block *self, unsigned long cmd, void *ptr)
 {
 	unsigned long flags;
-	TRAP_HANDLER_DECL;
+	int ret;
 
 	local_irq_save(flags);
-	kgdb_handle_exception(vec >> 2, SIGTRAP, 0, regs);
+	ret = __kgdb_notify(ptr, cmd);
 	local_irq_restore(flags);
+
+	return ret;
 }
 
+static struct notifier_block kgdb_notifier = {
+	.notifier_call	= kgdb_notify,
+
+	/*
+	 * Lowest-prio notifier priority, we want to be notified last:
+	 */
+	.priority	= -INT_MAX,
+};
+
 int kgdb_arch_init(void)
 {
-	return 0;
+	return register_die_notifier(&kgdb_notifier);
 }
 
 void kgdb_arch_exit(void)
 {
+	unregister_die_notifier(&kgdb_notifier);
 }
 
 struct kgdb_arch arch_kgdb_ops = {
diff --git a/arch/sh/kernel/machine_kexec.c b/arch/sh/kernel/machine_kexec.c
index 76f2802..7672141 100644
--- a/arch/sh/kernel/machine_kexec.c
+++ b/arch/sh/kernel/machine_kexec.c
@@ -21,6 +21,8 @@
 #include <asm/mmu_context.h>
 #include <asm/io.h>
 #include <asm/cacheflush.h>
+#include <asm/sh_bios.h>
+#include <asm/reboot.h>
 
 typedef void (*relocate_new_kernel_t)(unsigned long indirection_page,
 				      unsigned long reboot_code_buffer,
@@ -28,15 +30,11 @@
 
 extern const unsigned char relocate_new_kernel[];
 extern const unsigned int relocate_new_kernel_size;
-extern void *gdb_vbr_vector;
 extern void *vbr_base;
 
-void machine_shutdown(void)
+void native_machine_crash_shutdown(struct pt_regs *regs)
 {
-}
-
-void machine_crash_shutdown(struct pt_regs *regs)
-{
+	/* Nothing to do for UP, but definitely broken for SMP.. */
 }
 
 /*
@@ -117,11 +115,7 @@
 	kexec_info(image);
 	flush_cache_all();
 
-#if defined(CONFIG_SH_STANDARD_BIOS)
-	asm volatile("ldc %0, vbr" :
-		     : "r" (((unsigned long) gdb_vbr_vector) - 0x100)
-		     : "memory");
-#endif
+	sh_bios_vbr_reload();
 
 	/* now call it */
 	rnk = (relocate_new_kernel_t) reboot_code_buffer;
diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c
new file mode 100644
index 0000000..81add9b
--- /dev/null
+++ b/arch/sh/kernel/process.c
@@ -0,0 +1,100 @@
+#include <linux/mm.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+struct kmem_cache *task_xstate_cachep = NULL;
+unsigned int xstate_size;
+
+int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
+{
+	*dst = *src;
+
+	if (src->thread.xstate) {
+		dst->thread.xstate = kmem_cache_alloc(task_xstate_cachep,
+						      GFP_KERNEL);
+		if (!dst->thread.xstate)
+			return -ENOMEM;
+		memcpy(dst->thread.xstate, src->thread.xstate, xstate_size);
+	}
+
+	return 0;
+}
+
+void free_thread_xstate(struct task_struct *tsk)
+{
+	if (tsk->thread.xstate) {
+		kmem_cache_free(task_xstate_cachep, tsk->thread.xstate);
+		tsk->thread.xstate = NULL;
+	}
+}
+
+#if THREAD_SHIFT < PAGE_SHIFT
+static struct kmem_cache *thread_info_cache;
+
+struct thread_info *alloc_thread_info(struct task_struct *tsk)
+{
+	struct thread_info *ti;
+
+	ti = kmem_cache_alloc(thread_info_cache, GFP_KERNEL);
+	if (unlikely(ti == NULL))
+		return NULL;
+#ifdef CONFIG_DEBUG_STACK_USAGE
+	memset(ti, 0, THREAD_SIZE);
+#endif
+	return ti;
+}
+
+void free_thread_info(struct thread_info *ti)
+{
+	free_thread_xstate(ti->task);
+	kmem_cache_free(thread_info_cache, ti);
+}
+
+void thread_info_cache_init(void)
+{
+	thread_info_cache = kmem_cache_create("thread_info", THREAD_SIZE,
+					      THREAD_SIZE, SLAB_PANIC, NULL);
+}
+#else
+struct thread_info *alloc_thread_info(struct task_struct *tsk)
+{
+#ifdef CONFIG_DEBUG_STACK_USAGE
+	gfp_t mask = GFP_KERNEL | __GFP_ZERO;
+#else
+	gfp_t mask = GFP_KERNEL;
+#endif
+	return (struct thread_info *)__get_free_pages(mask, THREAD_SIZE_ORDER);
+}
+
+void free_thread_info(struct thread_info *ti)
+{
+	free_thread_xstate(ti->task);
+	free_pages((unsigned long)ti, THREAD_SIZE_ORDER);
+}
+#endif /* THREAD_SHIFT < PAGE_SHIFT */
+
+void arch_task_cache_init(void)
+{
+	if (!xstate_size)
+		return;
+
+	task_xstate_cachep = kmem_cache_create("task_xstate", xstate_size,
+					       __alignof__(union thread_xstate),
+					       SLAB_PANIC | SLAB_NOTRACK, NULL);
+}
+
+#ifdef CONFIG_SH_FPU_EMU
+# define HAVE_SOFTFP	1
+#else
+# define HAVE_SOFTFP	0
+#endif
+
+void init_thread_xstate(void)
+{
+	if (boot_cpu_data.flags & CPU_HAS_FPU)
+		xstate_size = sizeof(struct sh_fpu_hard_struct);
+	else if (HAVE_SOFTFP)
+		xstate_size = sizeof(struct sh_fpu_soft_struct);
+	else
+		xstate_size = 0;
+}
diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c
index d8af889..3cb88f1 100644
--- a/arch/sh/kernel/process_32.c
+++ b/arch/sh/kernel/process_32.c
@@ -16,65 +16,15 @@
 #include <linux/module.h>
 #include <linux/mm.h>
 #include <linux/elfcore.h>
-#include <linux/pm.h>
 #include <linux/kallsyms.h>
-#include <linux/kexec.h>
-#include <linux/kdebug.h>
-#include <linux/tick.h>
-#include <linux/reboot.h>
 #include <linux/fs.h>
 #include <linux/ftrace.h>
-#include <linux/preempt.h>
+#include <linux/hw_breakpoint.h>
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
-#include <asm/pgalloc.h>
 #include <asm/system.h>
-#include <asm/ubc.h>
 #include <asm/fpu.h>
 #include <asm/syscalls.h>
-#include <asm/watchdog.h>
-
-int ubc_usercnt = 0;
-
-#ifdef CONFIG_32BIT
-static void watchdog_trigger_immediate(void)
-{
-	sh_wdt_write_cnt(0xFF);
-	sh_wdt_write_csr(0xC2);
-}
-
-void machine_restart(char * __unused)
-{
-	local_irq_disable();
-
-	/* Use watchdog timer to trigger reset */
-	watchdog_trigger_immediate();
-
-	while (1)
-		cpu_sleep();
-}
-#else
-void machine_restart(char * __unused)
-{
-	/* SR.BL=1 and invoke address error to let CPU reset (manual reset) */
-	asm volatile("ldc %0, sr\n\t"
-		     "mov.l @%1, %0" : : "r" (0x10000000), "r" (0x80000001));
-}
-#endif
-
-void machine_halt(void)
-{
-	local_irq_disable();
-
-	while (1)
-		cpu_sleep();
-}
-
-void machine_power_off(void)
-{
-	if (pm_power_off)
-		pm_power_off();
-}
 
 void show_regs(struct pt_regs * regs)
 {
@@ -91,7 +41,7 @@
 	printk("PC  : %08lx SP  : %08lx SR  : %08lx ",
 	       regs->pc, regs->regs[15], regs->sr);
 #ifdef CONFIG_MMU
-	printk("TEA : %08x\n", ctrl_inl(MMU_TEA));
+	printk("TEA : %08x\n", __raw_readl(MMU_TEA));
 #else
 	printk("\n");
 #endif
@@ -147,21 +97,34 @@
 }
 EXPORT_SYMBOL(kernel_thread);
 
+void start_thread(struct pt_regs *regs, unsigned long new_pc,
+		  unsigned long new_sp)
+{
+	set_fs(USER_DS);
+
+	regs->pr = 0;
+	regs->sr = SR_FD;
+	regs->pc = new_pc;
+	regs->regs[15] = new_sp;
+
+	free_thread_xstate(current);
+}
+EXPORT_SYMBOL(start_thread);
+
 /*
  * Free current thread data structures etc..
  */
 void exit_thread(void)
 {
-	if (current->thread.ubc_pc) {
-		current->thread.ubc_pc = 0;
-		ubc_usercnt -= 1;
-	}
 }
 
 void flush_thread(void)
 {
-#if defined(CONFIG_SH_FPU)
 	struct task_struct *tsk = current;
+
+	flush_ptrace_hw_breakpoint(tsk);
+
+#if defined(CONFIG_SH_FPU)
 	/* Forget lazy FPU state */
 	clear_fpu(tsk, task_pt_regs(tsk));
 	clear_used_math();
@@ -209,11 +172,10 @@
 {
 	struct thread_info *ti = task_thread_info(p);
 	struct pt_regs *childregs;
-#if defined(CONFIG_SH_DSP)
-	struct task_struct *tsk = current;
-#endif
 
 #if defined(CONFIG_SH_DSP)
+	struct task_struct *tsk = current;
+
 	if (is_dsp_enabled(tsk)) {
 		/* We can use the __save_dsp or just copy the struct:
 		 * __save_dsp(p);
@@ -244,53 +206,11 @@
 	p->thread.sp = (unsigned long) childregs;
 	p->thread.pc = (unsigned long) ret_from_fork;
 
-	p->thread.ubc_pc = 0;
+	memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps));
 
 	return 0;
 }
 
-/* Tracing by user break controller.  */
-static void ubc_set_tracing(int asid, unsigned long pc)
-{
-#if defined(CONFIG_CPU_SH4A)
-	unsigned long val;
-
-	val = (UBC_CBR_ID_INST | UBC_CBR_RW_READ | UBC_CBR_CE);
-	val |= (UBC_CBR_AIE | UBC_CBR_AIV_SET(asid));
-
-	ctrl_outl(val, UBC_CBR0);
-	ctrl_outl(pc,  UBC_CAR0);
-	ctrl_outl(0x0, UBC_CAMR0);
-	ctrl_outl(0x0, UBC_CBCR);
-
-	val = (UBC_CRR_RES | UBC_CRR_PCB | UBC_CRR_BIE);
-	ctrl_outl(val, UBC_CRR0);
-
-	/* Read UBC register that we wrote last, for checking update */
-	val = ctrl_inl(UBC_CRR0);
-
-#else	/* CONFIG_CPU_SH4A */
-	ctrl_outl(pc, UBC_BARA);
-
-#ifdef CONFIG_MMU
-	ctrl_outb(asid, UBC_BASRA);
-#endif
-
-	ctrl_outl(0, UBC_BAMRA);
-
-	if (current_cpu_data.type == CPU_SH7729 ||
-	    current_cpu_data.type == CPU_SH7710 ||
-	    current_cpu_data.type == CPU_SH7712 ||
-	    current_cpu_data.type == CPU_SH7203){
-		ctrl_outw(BBR_INST | BBR_READ | BBR_CPU, UBC_BBRA);
-		ctrl_outl(BRCR_PCBA | BRCR_PCTE, UBC_BRCR);
-	} else {
-		ctrl_outw(BBR_INST | BBR_READ, UBC_BBRA);
-		ctrl_outw(BRCR_PCBA, UBC_BRCR);
-	}
-#endif	/* CONFIG_CPU_SH4A */
-}
-
 /*
  *	switch_to(x,y) should switch tasks from x to y.
  *
@@ -304,7 +224,7 @@
 
 	/* we're going to use this soon, after a few expensive things */
 	if (next->fpu_counter > 5)
-		prefetch(&next_t->fpu.hard);
+		prefetch(next_t->xstate);
 
 #ifdef CONFIG_MMU
 	/*
@@ -316,32 +236,13 @@
 		     : "r" (task_thread_info(next)));
 #endif
 
-	/* If no tasks are using the UBC, we're done */
-	if (ubc_usercnt == 0)
-		/* If no tasks are using the UBC, we're done */;
-	else if (next->thread.ubc_pc && next->mm) {
-		int asid = 0;
-#ifdef CONFIG_MMU
-		asid |= cpu_asid(smp_processor_id(), next->mm);
-#endif
-		ubc_set_tracing(asid, next->thread.ubc_pc);
-	} else {
-#if defined(CONFIG_CPU_SH4A)
-		ctrl_outl(UBC_CBR_INIT, UBC_CBR0);
-		ctrl_outl(UBC_CRR_INIT, UBC_CRR0);
-#else
-		ctrl_outw(0, UBC_BBRA);
-		ctrl_outw(0, UBC_BBRB);
-#endif
-	}
-
 	/*
 	 * If the task has used fpu the last 5 timeslices, just do a full
 	 * restore of the math state immediately to avoid the trap; the
 	 * chances of needing FPU soon are obviously high now
 	 */
 	if (next->fpu_counter > 5)
-		fpu_state_restore(task_pt_regs(next));
+		__fpu_state_restore();
 
 	return prev;
 }
@@ -434,20 +335,3 @@
 
 	return pc;
 }
-
-asmlinkage void break_point_trap(void)
-{
-	/* Clear tracing.  */
-#if defined(CONFIG_CPU_SH4A)
-	ctrl_outl(UBC_CBR_INIT, UBC_CBR0);
-	ctrl_outl(UBC_CRR_INIT, UBC_CRR0);
-#else
-	ctrl_outw(0, UBC_BBRA);
-	ctrl_outw(0, UBC_BBRB);
-	ctrl_outl(0, UBC_BRCR);
-#endif
-	current->thread.ubc_pc = 0;
-	ubc_usercnt -= 1;
-
-	force_sig(SIGTRAP, current);
-}
diff --git a/arch/sh/kernel/process_64.c b/arch/sh/kernel/process_64.c
index ec79faf..c90957a 100644
--- a/arch/sh/kernel/process_64.c
+++ b/arch/sh/kernel/process_64.c
@@ -32,30 +32,7 @@
 
 struct task_struct *last_task_used_math = NULL;
 
-void machine_restart(char * __unused)
-{
-	extern void phys_stext(void);
-
-	phys_stext();
-}
-
-void machine_halt(void)
-{
-	for (;;);
-}
-
-void machine_power_off(void)
-{
-	__asm__ __volatile__ (
-		"sleep\n\t"
-		"synci\n\t"
-		"nop;nop;nop;nop\n\t"
-	);
-
-	panic("Unexpected wakeup!\n");
-}
-
-void show_regs(struct pt_regs * regs)
+void show_regs(struct pt_regs *regs)
 {
 	unsigned long long ah, al, bh, bl, ch, cl;
 
@@ -410,7 +387,7 @@
 			regs->sr |= SR_FD;
 		}
 
-		memcpy(fpu, &tsk->thread.fpu.hard, sizeof(*fpu));
+		memcpy(fpu, &tsk->thread.xstate->hardfpu, sizeof(*fpu));
 	}
 
 	return fpvalid;
diff --git a/arch/sh/kernel/ptrace_32.c b/arch/sh/kernel/ptrace_32.c
index 9be35f3..c625cda 100644
--- a/arch/sh/kernel/ptrace_32.c
+++ b/arch/sh/kernel/ptrace_32.c
@@ -2,7 +2,7 @@
  * SuperH process tracing
  *
  * Copyright (C) 1999, 2000  Kaz Kojima & Niibe Yutaka
- * Copyright (C) 2002 - 2008  Paul Mundt
+ * Copyright (C) 2002 - 2009  Paul Mundt
  *
  * Audit support by Yuichi Nakamura <ynakam@hitachisoft.jp>
  *
@@ -26,6 +26,7 @@
 #include <linux/tracehook.h>
 #include <linux/elf.h>
 #include <linux/regset.h>
+#include <linux/hw_breakpoint.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
@@ -63,33 +64,64 @@
 	return 0;
 }
 
+void ptrace_triggered(struct perf_event *bp, int nmi,
+		      struct perf_sample_data *data, struct pt_regs *regs)
+{
+	struct perf_event_attr attr;
+
+	/*
+	 * Disable the breakpoint request here since ptrace has defined a
+	 * one-shot behaviour for breakpoint exceptions.
+	 */
+	attr = bp->attr;
+	attr.disabled = true;
+	modify_user_hw_breakpoint(bp, &attr);
+}
+
+static int set_single_step(struct task_struct *tsk, unsigned long addr)
+{
+	struct thread_struct *thread = &tsk->thread;
+	struct perf_event *bp;
+	struct perf_event_attr attr;
+
+	bp = thread->ptrace_bps[0];
+	if (!bp) {
+		hw_breakpoint_init(&attr);
+
+		attr.bp_addr = addr;
+		attr.bp_len = HW_BREAKPOINT_LEN_2;
+		attr.bp_type = HW_BREAKPOINT_R;
+
+		bp = register_user_hw_breakpoint(&attr, ptrace_triggered, tsk);
+		if (IS_ERR(bp))
+			return PTR_ERR(bp);
+
+		thread->ptrace_bps[0] = bp;
+	} else {
+		int err;
+
+		attr = bp->attr;
+		attr.bp_addr = addr;
+		err = modify_user_hw_breakpoint(bp, &attr);
+		if (unlikely(err))
+			return err;
+	}
+
+	return 0;
+}
+
 void user_enable_single_step(struct task_struct *child)
 {
-	/* Next scheduling will set up UBC */
-	if (child->thread.ubc_pc == 0)
-		ubc_usercnt += 1;
-
-	child->thread.ubc_pc = get_stack_long(child,
-				offsetof(struct pt_regs, pc));
+	unsigned long pc = get_stack_long(child, offsetof(struct pt_regs, pc));
 
 	set_tsk_thread_flag(child, TIF_SINGLESTEP);
+
+	set_single_step(child, pc);
 }
 
 void user_disable_single_step(struct task_struct *child)
 {
 	clear_tsk_thread_flag(child, TIF_SINGLESTEP);
-
-	/*
-	 * Ensure the UBC is not programmed at the next context switch.
-	 *
-	 * Normally this is not needed but there are sequences such as
-	 * singlestep, signal delivery, and continue that leave the
-	 * ubc_pc non-zero leading to spurious SIGTRAPs.
-	 */
-	if (child->thread.ubc_pc != 0) {
-		ubc_usercnt -= 1;
-		child->thread.ubc_pc = 0;
-	}
 }
 
 /*
@@ -163,10 +195,10 @@
 
 	if ((boot_cpu_data.flags & CPU_HAS_FPU))
 		return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
-					   &target->thread.fpu.hard, 0, -1);
+					   &target->thread.xstate->hardfpu, 0, -1);
 
 	return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
-				   &target->thread.fpu.soft, 0, -1);
+				   &target->thread.xstate->softfpu, 0, -1);
 }
 
 static int fpregs_set(struct task_struct *target,
@@ -184,10 +216,10 @@
 
 	if ((boot_cpu_data.flags & CPU_HAS_FPU))
 		return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
-					  &target->thread.fpu.hard, 0, -1);
+					  &target->thread.xstate->hardfpu, 0, -1);
 
 	return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
-				  &target->thread.fpu.soft, 0, -1);
+				  &target->thread.xstate->softfpu, 0, -1);
 }
 
 static int fpregs_active(struct task_struct *target,
@@ -333,7 +365,7 @@
 				else
 					tmp = 0;
 			} else
-				tmp = ((long *)&child->thread.fpu)
+				tmp = ((long *)child->thread.xstate)
 					[(addr - (long)&dummy->fpu) >> 2];
 		} else if (addr == (long) &dummy->u_fpvalid)
 			tmp = !!tsk_used_math(child);
@@ -362,7 +394,7 @@
 		else if (addr >= (long) &dummy->fpu &&
 			 addr < (long) &dummy->u_fpvalid) {
 			set_stopped_child_used_math(child);
-			((long *)&child->thread.fpu)
+			((long *)child->thread.xstate)
 				[(addr - (long)&dummy->fpu) >> 2] = data;
 			ret = 0;
 		} else if (addr == (long) &dummy->u_fpvalid) {
diff --git a/arch/sh/kernel/ptrace_64.c b/arch/sh/kernel/ptrace_64.c
index b063eb8..5fd644d 100644
--- a/arch/sh/kernel/ptrace_64.c
+++ b/arch/sh/kernel/ptrace_64.c
@@ -88,7 +88,7 @@
 		regs->sr |= SR_FD;
 	}
 
-	tmp = ((long *)&task->thread.fpu)[addr / sizeof(unsigned long)];
+	tmp = ((long *)task->thread.xstate)[addr / sizeof(unsigned long)];
 	return tmp;
 }
 
@@ -114,8 +114,7 @@
 	regs = (struct pt_regs*)((unsigned char *)task + THREAD_SIZE) - 1;
 
 	if (!tsk_used_math(task)) {
-		fpinit(&task->thread.fpu.hard);
-		set_stopped_child_used_math(task);
+		init_fpu(task);
 	} else if (last_task_used_math == task) {
 		enable_fpu();
 		save_fpu(task);
@@ -124,7 +123,7 @@
 		regs->sr |= SR_FD;
 	}
 
-	((long *)&task->thread.fpu)[addr / sizeof(unsigned long)] = data;
+	((long *)task->thread.xstate)[addr / sizeof(unsigned long)] = data;
 	return 0;
 }
 
@@ -226,7 +225,7 @@
 		return ret;
 
 	return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
-				   &target->thread.fpu.hard, 0, -1);
+				   &target->thread.xstate->hardfpu, 0, -1);
 }
 
 static int fpregs_set(struct task_struct *target,
@@ -243,7 +242,7 @@
 	set_stopped_child_used_math(target);
 
 	return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
-				  &target->thread.fpu.hard, 0, -1);
+				  &target->thread.xstate->hardfpu, 0, -1);
 }
 
 static int fpregs_active(struct task_struct *target,
@@ -486,9 +485,10 @@
 }
 
 /* Called with interrupts disabled */
-asmlinkage void do_software_break_point(unsigned long long vec,
-					struct pt_regs *regs)
+BUILD_TRAP_HANDLER(breakpoint)
 {
+	TRAP_HANDLER_DECL;
+
 	/* We need to forward step the PC, to counteract the backstep done
 	   in signal.c. */
 	local_irq_enable();
diff --git a/arch/sh/kernel/reboot.c b/arch/sh/kernel/reboot.c
new file mode 100644
index 0000000..b1fca66
--- /dev/null
+++ b/arch/sh/kernel/reboot.c
@@ -0,0 +1,98 @@
+#include <linux/pm.h>
+#include <linux/kexec.h>
+#include <linux/kernel.h>
+#include <linux/reboot.h>
+#include <linux/module.h>
+#ifdef CONFIG_SUPERH32
+#include <asm/watchdog.h>
+#endif
+#include <asm/addrspace.h>
+#include <asm/reboot.h>
+#include <asm/system.h>
+
+void (*pm_power_off)(void);
+EXPORT_SYMBOL(pm_power_off);
+
+#ifdef CONFIG_SUPERH32
+static void watchdog_trigger_immediate(void)
+{
+	sh_wdt_write_cnt(0xFF);
+	sh_wdt_write_csr(0xC2);
+}
+#endif
+
+static void native_machine_restart(char * __unused)
+{
+	local_irq_disable();
+
+	/* Address error with SR.BL=1 first. */
+	trigger_address_error();
+
+#ifdef CONFIG_SUPERH32
+	/* If that fails or is unsupported, go for the watchdog next. */
+	watchdog_trigger_immediate();
+#endif
+
+	/*
+	 * Give up and sleep.
+	 */
+	while (1)
+		cpu_sleep();
+}
+
+static void native_machine_shutdown(void)
+{
+	smp_send_stop();
+}
+
+static void native_machine_power_off(void)
+{
+	if (pm_power_off)
+		pm_power_off();
+}
+
+static void native_machine_halt(void)
+{
+	/* stop other cpus */
+	machine_shutdown();
+
+	/* stop this cpu */
+	stop_this_cpu(NULL);
+}
+
+struct machine_ops machine_ops = {
+	.power_off	= native_machine_power_off,
+	.shutdown	= native_machine_shutdown,
+	.restart	= native_machine_restart,
+	.halt		= native_machine_halt,
+#ifdef CONFIG_KEXEC
+	.crash_shutdown = native_machine_crash_shutdown,
+#endif
+};
+
+void machine_power_off(void)
+{
+	machine_ops.power_off();
+}
+
+void machine_shutdown(void)
+{
+	machine_ops.shutdown();
+}
+
+void machine_restart(char *cmd)
+{
+	machine_ops.restart(cmd);
+}
+
+void machine_halt(void)
+{
+	machine_ops.halt();
+}
+
+#ifdef CONFIG_KEXEC
+void machine_crash_shutdown(struct pt_regs *regs)
+{
+	machine_ops.crash_shutdown(regs);
+}
+#endif
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index 8b0e697..3459e70 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -421,6 +421,8 @@
 
 	parse_early_param();
 
+	uncached_init();
+
 	plat_early_device_setup();
 
 	/* Let earlyprintk output early console messages */
@@ -449,17 +451,15 @@
 #ifdef CONFIG_DUMMY_CONSOLE
 	conswitchp = &dummy_con;
 #endif
+	paging_init();
+	pmb_init();
+
+	ioremap_fixed_init();
 
 	/* Perform the machine specific initialisation */
 	if (likely(sh_mv.mv_setup))
 		sh_mv.mv_setup(cmdline_p);
 
-	paging_init();
-
-#ifdef CONFIG_PMB_ENABLE
-	pmb_init();
-#endif
-
 #ifdef CONFIG_SMP
 	plat_smp_setup();
 #endif
diff --git a/arch/sh/kernel/sh_bios.c b/arch/sh/kernel/sh_bios.c
index c852f78..47475cc 100644
--- a/arch/sh/kernel/sh_bios.c
+++ b/arch/sh/kernel/sh_bios.c
@@ -1,19 +1,30 @@
 /*
- *  linux/arch/sh/kernel/sh_bios.c
  *  C interface for trapping into the standard LinuxSH BIOS.
  *
  *  Copyright (C) 2000 Greg Banks, Mitch Davis
+ *  Copyright (C) 1999, 2000  Niibe Yutaka
+ *  Copyright (C) 2002  M. R. Brown
+ *  Copyright (C) 2004 - 2010  Paul Mundt
  *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
  */
 #include <linux/module.h>
+#include <linux/console.h>
+#include <linux/tty.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/delay.h>
 #include <asm/sh_bios.h>
 
 #define BIOS_CALL_CONSOLE_WRITE		0
 #define BIOS_CALL_ETH_NODE_ADDR		10
 #define BIOS_CALL_SHUTDOWN		11
-#define BIOS_CALL_CHAR_OUT		0x1f	/* TODO: hack */
 #define BIOS_CALL_GDB_DETACH		0xff
 
+void *gdb_vbr_vector = NULL;
+
 static inline long sh_bios_call(long func, long arg0, long arg1, long arg2,
 				    long arg3)
 {
@@ -23,6 +34,9 @@
 	register long r6 __asm__("r6") = arg2;
 	register long r7 __asm__("r7") = arg3;
 
+	if (!gdb_vbr_vector)
+		return -ENOSYS;
+
 	__asm__ __volatile__("trapa	#0x3f":"=z"(r0)
 			     :"0"(r0), "r"(r4), "r"(r5), "r"(r6), "r"(r7)
 			     :"memory");
@@ -34,11 +48,6 @@
 	sh_bios_call(BIOS_CALL_CONSOLE_WRITE, (long)buf, (long)len, 0, 0);
 }
 
-void sh_bios_char_out(char ch)
-{
-	sh_bios_call(BIOS_CALL_CHAR_OUT, ch, 0, 0, 0);
-}
-
 void sh_bios_gdb_detach(void)
 {
 	sh_bios_call(BIOS_CALL_GDB_DETACH, 0, 0, 0, 0);
@@ -55,3 +64,109 @@
 {
 	sh_bios_call(BIOS_CALL_SHUTDOWN, how, 0, 0, 0);
 }
+
+/*
+ * Read the old value of the VBR register to initialise the vector
+ * through which debug and BIOS traps are delegated by the Linux trap
+ * handler.
+ */
+void sh_bios_vbr_init(void)
+{
+	unsigned long vbr;
+
+	if (unlikely(gdb_vbr_vector))
+		return;
+
+	__asm__ __volatile__ ("stc vbr, %0" : "=r" (vbr));
+
+	if (vbr) {
+		gdb_vbr_vector = (void *)(vbr + 0x100);
+		printk(KERN_NOTICE "Setting GDB trap vector to %p\n",
+		       gdb_vbr_vector);
+	} else
+		printk(KERN_NOTICE "SH-BIOS not detected\n");
+}
+
+/**
+ * sh_bios_vbr_reload - Re-load the system VBR from the BIOS vector.
+ *
+ * This can be used by save/restore code to reinitialize the system VBR
+ * from the fixed BIOS VBR. A no-op if no BIOS VBR is known.
+ */
+void sh_bios_vbr_reload(void)
+{
+	if (gdb_vbr_vector)
+		__asm__ __volatile__ (
+			"ldc %0, vbr"
+			:
+			: "r" (((unsigned long) gdb_vbr_vector) - 0x100)
+			: "memory"
+		);
+}
+
+/*
+ *	Print a string through the BIOS
+ */
+static void sh_console_write(struct console *co, const char *s,
+				 unsigned count)
+{
+	sh_bios_console_write(s, count);
+}
+
+/*
+ *	Setup initial baud/bits/parity. We do two things here:
+ *	- construct a cflag setting for the first rs_open()
+ *	- initialize the serial port
+ *	Return non-zero if we didn't find a serial port.
+ */
+static int __init sh_console_setup(struct console *co, char *options)
+{
+	int	cflag = CREAD | HUPCL | CLOCAL;
+
+	/*
+	 *	Now construct a cflag setting.
+	 *	TODO: this is a totally bogus cflag, as we have
+	 *	no idea what serial settings the BIOS is using, or
+	 *	even if its using the serial port at all.
+	 */
+	cflag |= B115200 | CS8 | /*no parity*/0;
+
+	co->cflag = cflag;
+
+	return 0;
+}
+
+static struct console bios_console = {
+	.name		= "bios",
+	.write		= sh_console_write,
+	.setup		= sh_console_setup,
+	.flags		= CON_PRINTBUFFER,
+	.index		= -1,
+};
+
+static struct console *early_console;
+
+static int __init setup_early_printk(char *buf)
+{
+	int keep_early = 0;
+
+	if (!buf)
+		return 0;
+
+	if (strstr(buf, "keep"))
+		keep_early = 1;
+
+	if (!strncmp(buf, "bios", 4))
+		early_console = &bios_console;
+
+	if (likely(early_console)) {
+		if (keep_early)
+			early_console->flags &= ~CON_BOOT;
+		else
+			early_console->flags |= CON_BOOT;
+		register_console(early_console);
+	}
+
+	return 0;
+}
+early_param("earlyprintk", setup_early_printk);
diff --git a/arch/sh/kernel/signal_32.c b/arch/sh/kernel/signal_32.c
index 12815ce..579cd2c 100644
--- a/arch/sh/kernel/signal_32.c
+++ b/arch/sh/kernel/signal_32.c
@@ -150,7 +150,7 @@
 		return 0;
 
 	set_used_math();
-	return __copy_from_user(&tsk->thread.fpu.hard, &sc->sc_fpregs[0],
+	return __copy_from_user(&tsk->thread.xstate->hardfpu, &sc->sc_fpregs[0],
 				sizeof(long)*(16*2+2));
 }
 
@@ -175,7 +175,7 @@
 	clear_used_math();
 
 	unlazy_fpu(tsk, regs);
-	return __copy_to_user(&sc->sc_fpregs[0], &tsk->thread.fpu.hard,
+	return __copy_to_user(&sc->sc_fpregs[0], &tsk->thread.xstate->hardfpu,
 			      sizeof(long)*(16*2+2));
 }
 #endif /* CONFIG_SH_FPU */
@@ -528,7 +528,7 @@
 		/* fallthrough */
 		case -ERESTARTNOINTR:
 			regs->regs[0] = save_r0;
-			regs->pc -= instruction_size(ctrl_inw(regs->pc - 4));
+			regs->pc -= instruction_size(__raw_readw(regs->pc - 4));
 			break;
 	}
 }
@@ -626,9 +626,9 @@
 		    regs->regs[0] == -ERESTARTSYS ||
 		    regs->regs[0] == -ERESTARTNOINTR) {
 			regs->regs[0] = save_r0;
-			regs->pc -= instruction_size(ctrl_inw(regs->pc - 4));
+			regs->pc -= instruction_size(__raw_readw(regs->pc - 4));
 		} else if (regs->regs[0] == -ERESTART_RESTARTBLOCK) {
-			regs->pc -= instruction_size(ctrl_inw(regs->pc - 4));
+			regs->pc -= instruction_size(__raw_readw(regs->pc - 4));
 			regs->regs[3] = __NR_restart_syscall;
 		}
 	}
diff --git a/arch/sh/kernel/signal_64.c b/arch/sh/kernel/signal_64.c
index 580e97d..5a9f1f1 100644
--- a/arch/sh/kernel/signal_64.c
+++ b/arch/sh/kernel/signal_64.c
@@ -297,7 +297,7 @@
 		regs->sr |= SR_FD;
 	}
 
-	err |= __copy_from_user(&current->thread.fpu.hard, &sc->sc_fpregs[0],
+	err |= __copy_from_user(&current->thread.xstate->hardfpu, &sc->sc_fpregs[0],
 				(sizeof(long long) * 32) + (sizeof(int) * 1));
 
 	return err;
@@ -322,7 +322,7 @@
 		regs->sr |= SR_FD;
 	}
 
-	err |= __copy_to_user(&sc->sc_fpregs[0], &current->thread.fpu.hard,
+	err |= __copy_to_user(&sc->sc_fpregs[0], &current->thread.xstate->hardfpu,
 			      (sizeof(long long) * 32) + (sizeof(int) * 1));
 	clear_used_math();
 
diff --git a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c
index 983e079..e124cf7 100644
--- a/arch/sh/kernel/smp.c
+++ b/arch/sh/kernel/smp.c
@@ -161,15 +161,6 @@
 	plat_send_ipi(cpu, SMP_MSG_RESCHEDULE);
 }
 
-static void stop_this_cpu(void *unused)
-{
-	cpu_clear(smp_processor_id(), cpu_online_map);
-	local_irq_disable();
-
-	for (;;)
-		cpu_relax();
-}
-
 void smp_send_stop(void)
 {
 	smp_call_function(stop_this_cpu, 0, 0);
diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c
index 7b03633..0830c2a 100644
--- a/arch/sh/kernel/traps.c
+++ b/arch/sh/kernel/traps.c
@@ -58,7 +58,7 @@
 	TRAP_HANDLER_DECL;
 
 	/* Rewind */
-	regs->pc -= instruction_size(ctrl_inw(regs->pc - 4));
+	regs->pc -= instruction_size(__raw_readw(regs->pc - 4));
 
 	if (notify_die(DIE_TRAP, "debug trap", regs, 0, vec & 0xff,
 		       SIGTRAP) == NOTIFY_STOP)
@@ -75,7 +75,7 @@
 	TRAP_HANDLER_DECL;
 
 	/* Rewind */
-	regs->pc -= instruction_size(ctrl_inw(regs->pc - 4));
+	regs->pc -= instruction_size(__raw_readw(regs->pc - 4));
 
 	if (notify_die(DIE_TRAP, "bug trap", regs, 0, TRAPA_BUG_OPCODE & 0xff,
 		       SIGTRAP) == NOTIFY_STOP)
diff --git a/arch/sh/kernel/traps_32.c b/arch/sh/kernel/traps_32.c
index 86639be..c3d86fa 100644
--- a/arch/sh/kernel/traps_32.c
+++ b/arch/sh/kernel/traps_32.c
@@ -24,11 +24,10 @@
 #include <linux/kdebug.h>
 #include <linux/kexec.h>
 #include <linux/limits.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
 #include <linux/sysfs.h>
+#include <linux/uaccess.h>
 #include <asm/system.h>
-#include <asm/uaccess.h>
+#include <asm/alignment.h>
 #include <asm/fpu.h>
 #include <asm/kprobes.h>
 
@@ -47,73 +46,6 @@
 #define TRAP_ILLEGAL_SLOT_INST	13
 #endif
 
-static unsigned long se_user;
-static unsigned long se_sys;
-static unsigned long se_half;
-static unsigned long se_word;
-static unsigned long se_dword;
-static unsigned long se_multi;
-/* bitfield: 1: warn 2: fixup 4: signal -> combinations 2|4 && 1|2|4 are not
-   valid! */
-static int se_usermode = 3;
-/* 0: no warning 1: print a warning message, disabled by default */
-static int se_kernmode_warn;
-
-#ifdef CONFIG_PROC_FS
-static const char *se_usermode_action[] = {
-	"ignored",
-	"warn",
-	"fixup",
-	"fixup+warn",
-	"signal",
-	"signal+warn"
-};
-
-static int alignment_proc_show(struct seq_file *m, void *v)
-{
-	seq_printf(m, "User:\t\t%lu\n", se_user);
-	seq_printf(m, "System:\t\t%lu\n", se_sys);
-	seq_printf(m, "Half:\t\t%lu\n", se_half);
-	seq_printf(m, "Word:\t\t%lu\n", se_word);
-	seq_printf(m, "DWord:\t\t%lu\n", se_dword);
-	seq_printf(m, "Multi:\t\t%lu\n", se_multi);
-	seq_printf(m, "User faults:\t%i (%s)\n", se_usermode,
-			se_usermode_action[se_usermode]);
-	seq_printf(m, "Kernel faults:\t%i (fixup%s)\n", se_kernmode_warn,
-			se_kernmode_warn ? "+warn" : "");
-	return 0;
-}
-
-static int alignment_proc_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, alignment_proc_show, NULL);
-}
-
-static ssize_t alignment_proc_write(struct file *file,
-		const char __user *buffer, size_t count, loff_t *pos)
-{
-	int *data = PDE(file->f_path.dentry->d_inode)->data;
-	char mode;
-
-	if (count > 0) {
-		if (get_user(mode, buffer))
-			return -EFAULT;
-		if (mode >= '0' && mode <= '5')
-			*data = mode - '0';
-	}
-	return count;
-}
-
-static const struct file_operations alignment_proc_fops = {
-	.owner		= THIS_MODULE,
-	.open		= alignment_proc_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-	.write		= alignment_proc_write,
-};
-#endif
-
 static void dump_mem(const char *str, unsigned long bottom, unsigned long top)
 {
 	unsigned long p;
@@ -265,10 +197,10 @@
 	count = 1<<(instruction&3);
 
 	switch (count) {
-	case 1: se_half  += 1; break;
-	case 2: se_word  += 1; break;
-	case 4: se_dword += 1; break;
-	case 8: se_multi += 1; break; /* ??? */
+	case 1: inc_unaligned_byte_access(); break;
+	case 2: inc_unaligned_word_access(); break;
+	case 4: inc_unaligned_dword_access(); break;
+	case 8: inc_unaligned_multi_access(); break;
 	}
 
 	ret = -EFAULT;
@@ -452,18 +384,8 @@
 	rm = regs->regs[index];
 
 	/* shout about fixups */
-	if (!expected) {
-		if (user_mode(regs) && (se_usermode & 1) && printk_ratelimit())
-			pr_notice("Fixing up unaligned userspace access "
-				  "in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n",
-				  current->comm, task_pid_nr(current),
-				  (void *)regs->pc, instruction);
-		else if (se_kernmode_warn && printk_ratelimit())
-			pr_notice("Fixing up unaligned kernel access "
-				  "in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n",
-				  current->comm, task_pid_nr(current),
-				  (void *)regs->pc, instruction);
-	}
+	if (!expected)
+		unaligned_fixups_notify(current, instruction, regs);
 
 	ret = -EFAULT;
 	switch (instruction&0xF000) {
@@ -616,10 +538,10 @@
 
 	if (user_mode(regs)) {
 		int si_code = BUS_ADRERR;
+		unsigned int user_action;
 
 		local_irq_enable();
-
-		se_user += 1;
+		inc_unaligned_user_access();
 
 		set_fs(USER_DS);
 		if (copy_from_user(&instruction, (insn_size_t *)(regs->pc & ~1),
@@ -630,16 +552,12 @@
 		set_fs(oldfs);
 
 		/* shout about userspace fixups */
-		if (se_usermode & 1)
-			printk(KERN_NOTICE "Unaligned userspace access "
-			       "in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n",
-			       current->comm, current->pid, (void *)regs->pc,
-			       instruction);
+		unaligned_fixups_notify(current, instruction, regs);
 
-		if (se_usermode & 2)
+		user_action = unaligned_user_action();
+		if (user_action & UM_FIXUP)
 			goto fixup;
-
-		if (se_usermode & 4)
+		if (user_action & UM_SIGNAL)
 			goto uspace_segv;
 		else {
 			/* ignore */
@@ -659,7 +577,7 @@
 					      &user_mem_access, 0);
 		set_fs(oldfs);
 
-		if (tmp==0)
+		if (tmp == 0)
 			return; /* sorted */
 uspace_segv:
 		printk(KERN_NOTICE "Sending SIGBUS to \"%s\" due to unaligned "
@@ -672,7 +590,7 @@
 		info.si_addr = (void __user *)address;
 		force_sig_info(SIGBUS, &info, current);
 	} else {
-		se_sys += 1;
+		inc_unaligned_kernel_access();
 
 		if (regs->pc & 1)
 			die("unaligned program counter", regs, error_code);
@@ -687,11 +605,7 @@
 			die("insn faulting in do_address_error", regs, 0);
 		}
 
-		if (se_kernmode_warn)
-			printk(KERN_NOTICE "Unaligned kernel access "
-			       "on behalf of \"%s\" pid=%d pc=0x%p ins=0x%04hx\n",
-			       current->comm, current->pid, (void *)regs->pc,
-			       instruction);
+		unaligned_fixups_notify(current, instruction, regs);
 
 		handle_unaligned_access(instruction, regs,
 					&user_mem_access, 0);
@@ -876,35 +790,10 @@
 	die_if_kernel("exception", regs, ex);
 }
 
-#if defined(CONFIG_SH_STANDARD_BIOS)
-void *gdb_vbr_vector;
-
-static inline void __init gdb_vbr_init(void)
-{
-	register unsigned long vbr;
-
-	/*
-	 * Read the old value of the VBR register to initialise
-	 * the vector through which debug and BIOS traps are
-	 * delegated by the Linux trap handler.
-	 */
-	asm volatile("stc vbr, %0" : "=r" (vbr));
-
-	gdb_vbr_vector = (void *)(vbr + 0x100);
-	printk("Setting GDB trap vector to 0x%08lx\n",
-	       (unsigned long)gdb_vbr_vector);
-}
-#endif
-
 void __cpuinit per_cpu_trap_init(void)
 {
 	extern void *vbr_base;
 
-#ifdef CONFIG_SH_STANDARD_BIOS
-	if (raw_smp_processor_id() == 0)
-		gdb_vbr_init();
-#endif
-
 	/* NOTE: The VBR value should be at P1
 	   (or P2, virtural "fixed" address space).
 	   It's definitely should not in physical address.  */
@@ -956,11 +845,8 @@
 #endif
 
 #ifdef TRAP_UBC
-	set_exception_table_vec(TRAP_UBC, break_point_trap);
+	set_exception_table_vec(TRAP_UBC, breakpoint_trap_handler);
 #endif
-
-	/* Setup VBR for boot cpu */
-	per_cpu_trap_init();
 }
 
 void show_stack(struct task_struct *tsk, unsigned long *sp)
@@ -985,34 +871,3 @@
 	show_stack(NULL, NULL);
 }
 EXPORT_SYMBOL(dump_stack);
-
-#ifdef CONFIG_PROC_FS
-/*
- * This needs to be done after sysctl_init, otherwise sys/ will be
- * overwritten.  Actually, this shouldn't be in sys/ at all since
- * it isn't a sysctl, and it doesn't contain sysctl information.
- * We now locate it in /proc/cpu/alignment instead.
- */
-static int __init alignment_init(void)
-{
-	struct proc_dir_entry *dir, *res;
-
-	dir = proc_mkdir("cpu", NULL);
-	if (!dir)
-		return -ENOMEM;
-
-	res = proc_create_data("alignment", S_IWUSR | S_IRUGO, dir,
-			       &alignment_proc_fops, &se_usermode);
-	if (!res)
-		return -ENOMEM;
-
-        res = proc_create_data("kernel_alignment", S_IWUSR | S_IRUGO, dir,
-			       &alignment_proc_fops, &se_kernmode_warn);
-        if (!res)
-                return -ENOMEM;
-
-	return 0;
-}
-
-fs_initcall(alignment_init);
-#endif
diff --git a/arch/sh/kernel/traps_64.c b/arch/sh/kernel/traps_64.c
index d86f531..e3f92eb 100644
--- a/arch/sh/kernel/traps_64.c
+++ b/arch/sh/kernel/traps_64.c
@@ -611,19 +611,19 @@
 
 		switch (width_shift) {
 		case 2:
-			current->thread.fpu.hard.fp_regs[destreg] = buflo;
+			current->thread.xstate->hardfpu.fp_regs[destreg] = buflo;
 			break;
 		case 3:
 			if (do_paired_load) {
-				current->thread.fpu.hard.fp_regs[destreg] = buflo;
-				current->thread.fpu.hard.fp_regs[destreg+1] = bufhi;
+				current->thread.xstate->hardfpu.fp_regs[destreg] = buflo;
+				current->thread.xstate->hardfpu.fp_regs[destreg+1] = bufhi;
 			} else {
 #if defined(CONFIG_CPU_LITTLE_ENDIAN)
-				current->thread.fpu.hard.fp_regs[destreg] = bufhi;
-				current->thread.fpu.hard.fp_regs[destreg+1] = buflo;
+				current->thread.xstate->hardfpu.fp_regs[destreg] = bufhi;
+				current->thread.xstate->hardfpu.fp_regs[destreg+1] = buflo;
 #else
-				current->thread.fpu.hard.fp_regs[destreg] = buflo;
-				current->thread.fpu.hard.fp_regs[destreg+1] = bufhi;
+				current->thread.xstate->hardfpu.fp_regs[destreg] = buflo;
+				current->thread.xstate->hardfpu.fp_regs[destreg+1] = bufhi;
 #endif
 			}
 			break;
@@ -681,19 +681,19 @@
 
 		switch (width_shift) {
 		case 2:
-			buflo = current->thread.fpu.hard.fp_regs[srcreg];
+			buflo = current->thread.xstate->hardfpu.fp_regs[srcreg];
 			break;
 		case 3:
 			if (do_paired_load) {
-				buflo = current->thread.fpu.hard.fp_regs[srcreg];
-				bufhi = current->thread.fpu.hard.fp_regs[srcreg+1];
+				buflo = current->thread.xstate->hardfpu.fp_regs[srcreg];
+				bufhi = current->thread.xstate->hardfpu.fp_regs[srcreg+1];
 			} else {
 #if defined(CONFIG_CPU_LITTLE_ENDIAN)
-				bufhi = current->thread.fpu.hard.fp_regs[srcreg];
-				buflo = current->thread.fpu.hard.fp_regs[srcreg+1];
+				bufhi = current->thread.xstate->hardfpu.fp_regs[srcreg];
+				buflo = current->thread.xstate->hardfpu.fp_regs[srcreg+1];
 #else
-				buflo = current->thread.fpu.hard.fp_regs[srcreg];
-				bufhi = current->thread.fpu.hard.fp_regs[srcreg+1];
+				buflo = current->thread.xstate->hardfpu.fp_regs[srcreg];
+				bufhi = current->thread.xstate->hardfpu.fp_regs[srcreg+1];
 #endif
 			}
 			break;
diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S
index a1e4ec2..7f8a709 100644
--- a/arch/sh/kernel/vmlinux.lds.S
+++ b/arch/sh/kernel/vmlinux.lds.S
@@ -3,7 +3,7 @@
  * Written by Niibe Yutaka and Paul Mundt
  */
 #ifdef CONFIG_SUPERH64
-#define LOAD_OFFSET	CONFIG_PAGE_OFFSET
+#define LOAD_OFFSET	PAGE_OFFSET
 OUTPUT_ARCH(sh:sh5)
 #else
 #define LOAD_OFFSET	0
@@ -14,17 +14,16 @@
 #include <asm/cache.h>
 #include <asm/vmlinux.lds.h>
 
+#ifdef CONFIG_PMB
+ #define MEMORY_OFFSET	0
+#else
+ #define MEMORY_OFFSET	__MEMORY_START
+#endif
+
 ENTRY(_start)
 SECTIONS
 {
-#ifdef CONFIG_PMB_FIXED
-	. = CONFIG_PAGE_OFFSET + (CONFIG_MEMORY_START & 0x1fffffff) +
-	    CONFIG_ZERO_PAGE_OFFSET;
-#elif defined(CONFIG_32BIT)
-	. = CONFIG_PAGE_OFFSET + CONFIG_ZERO_PAGE_OFFSET;
-#else
-	. = CONFIG_PAGE_OFFSET + CONFIG_MEMORY_START + CONFIG_ZERO_PAGE_OFFSET;
-#endif
+	. = PAGE_OFFSET + MEMORY_OFFSET + CONFIG_ZERO_PAGE_OFFSET;
 
 	_text = .;		/* Text and read-only data */
 
@@ -35,12 +34,7 @@
 	.text : AT(ADDR(.text) - LOAD_OFFSET) {
 		HEAD_TEXT
 		TEXT_TEXT
-
-#ifdef CONFIG_SUPERH64
-		*(.text64)
-		*(.text..SHmedia32)
-#endif
-
+		EXTRA_TEXT
 		SCHED_TEXT
 		LOCK_TEXT
 		KPROBES_TEXT
@@ -51,24 +45,12 @@
 	} = 0x0009
 
 	EXCEPTION_TABLE(16)
-
 	NOTES
+
+	_sdata = .;
 	RO_DATA(PAGE_SIZE)
-
-	/*
-	 * Code which must be executed uncached and the associated data
-	 */
-	. = ALIGN(PAGE_SIZE);
-	.uncached : AT(ADDR(.uncached) - LOAD_OFFSET) {
-		__uncached_start = .;
-		*(.uncached.text)
-		*(.uncached.data)
-		__uncached_end = .;
-	}
-
 	RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
-
-	_edata = .;			/* End of data section */
+	_edata = .;
 
 	DWARF_EH_FRAME
 
diff --git a/arch/sh/math-emu/math.c b/arch/sh/math-emu/math.c
index d6c15ca..1fcdb12 100644
--- a/arch/sh/math-emu/math.c
+++ b/arch/sh/math-emu/math.c
@@ -471,10 +471,10 @@
  *	denormal_to_double - Given denormalized float number,
  *	                     store double float
  *
- *	@fpu: Pointer to sh_fpu_hard structure
+ *	@fpu: Pointer to sh_fpu_soft structure
  *	@n: Index to FP register
  */
-static void denormal_to_double(struct sh_fpu_hard_struct *fpu, int n)
+static void denormal_to_double(struct sh_fpu_soft_struct *fpu, int n)
 {
 	unsigned long du, dl;
 	unsigned long x = fpu->fpul;
@@ -552,11 +552,11 @@
 	if ((finsn & 0xf1ff) == 0xf0ad) { /* fcnvsd */
 		struct task_struct *tsk = current;
 
-		if ((tsk->thread.fpu.hard.fpscr & (1 << 17))) {
+		if ((tsk->thread.xstate->softfpu.fpscr & (1 << 17))) {
 			/* FPU error */
-			denormal_to_double (&tsk->thread.fpu.hard,
+			denormal_to_double (&tsk->thread.xstate->softfpu,
 					    (finsn >> 8) & 0xf);
-			tsk->thread.fpu.hard.fpscr &=
+			tsk->thread.xstate->softfpu.fpscr &=
 				~(FPSCR_CAUSE_MASK | FPSCR_FLAG_MASK);
 			task_thread_info(tsk)->status |= TS_USEDFPU;
 		} else {
@@ -617,7 +617,7 @@
 int do_fpu_inst(unsigned short inst, struct pt_regs *regs)
 {
 	struct task_struct *tsk = current;
-	struct sh_fpu_soft_struct *fpu = &(tsk->thread.fpu.soft);
+	struct sh_fpu_soft_struct *fpu = &(tsk->thread.xstate->softfpu);
 
 	if (!(task_thread_info(tsk)->status & TS_USEDFPU)) {
 		/* initialize once. */
diff --git a/arch/sh/mm/Kconfig b/arch/sh/mm/Kconfig
index 986a71b..1445ca6 100644
--- a/arch/sh/mm/Kconfig
+++ b/arch/sh/mm/Kconfig
@@ -75,52 +75,25 @@
 config 29BIT
 	def_bool !32BIT
 	depends on SUPERH32
+	select UNCACHED_MAPPING
 
 config 32BIT
 	bool
 	default y if CPU_SH5
 
-config PMB_ENABLE
+config PMB
 	bool "Support 32-bit physical addressing through PMB"
 	depends on MMU && EXPERIMENTAL && CPU_SH4A && !CPU_SH4AL_DSP
-	help
-	  If you say Y here, physical addressing will be extended to
-	  32-bits through the SH-4A PMB. If this is not set, legacy
-	  29-bit physical addressing will be used.
-
-choice
-	prompt "PMB handling type"
-	depends on PMB_ENABLE
-	default PMB_FIXED
-
-config PMB
-	bool "PMB"
-	depends on MMU && EXPERIMENTAL && CPU_SH4A && !CPU_SH4AL_DSP
-	help
-	  If you say Y here, physical addressing will be extended to
-	  32-bits through the SH-4A PMB. If this is not set, legacy
-	  29-bit physical addressing will be used.
-
-config PMB_FIXED
-	bool "fixed PMB"
-	depends on MMU && EXPERIMENTAL && CPU_SH4A && !CPU_SH4AL_DSP
 	select 32BIT
+	select UNCACHED_MAPPING
 	help
-	  If this option is enabled, fixed PMB mappings are inherited
-	  from the boot loader, and the kernel does not attempt dynamic
-	  management. This is the closest to legacy 29-bit physical mode,
-	  and allows systems to support up to 512MiB of system memory.
-
-endchoice
+	  If you say Y here, physical addressing will be extended to
+	  32-bits through the SH-4A PMB. If this is not set, legacy
+	  29-bit physical addressing will be used.
 
 config X2TLB
-	bool "Enable extended TLB mode"
-	depends on (CPU_SHX2 || CPU_SHX3) && MMU && EXPERIMENTAL
-	help
-	  Selecting this option will enable the extended mode of the SH-X2
-	  TLB. For legacy SH-X behaviour and interoperability, say N. For
-	  all of the fun new features and a willingless to submit bug reports,
-	  say Y.
+	def_bool y
+	depends on (CPU_SHX2 || CPU_SHX3) && MMU
 
 config VSYSCALL
 	bool "Support vsyscall page"
@@ -188,14 +161,19 @@
 	def_bool y
 	depends on MEMORY_HOTPLUG
 
+config IOREMAP_FIXED
+       def_bool y
+       depends on X2TLB || SUPERH64
+
+config UNCACHED_MAPPING
+	bool
+
 choice
 	prompt "Kernel page size"
-	default PAGE_SIZE_8KB if X2TLB
 	default PAGE_SIZE_4KB
 
 config PAGE_SIZE_4KB
 	bool "4kB"
-	depends on !MMU || !X2TLB
 	help
 	  This is the default page size used by all SuperH CPUs.
 
diff --git a/arch/sh/mm/Makefile b/arch/sh/mm/Makefile
index 8a70535..3dc8a8a 100644
--- a/arch/sh/mm/Makefile
+++ b/arch/sh/mm/Makefile
@@ -2,7 +2,7 @@
 # Makefile for the Linux SuperH-specific parts of the memory manager.
 #
 
-obj-y			:= cache.o init.o consistent.o mmap.o
+obj-y			:= alignment.o cache.o init.o consistent.o mmap.o
 
 cacheops-$(CONFIG_CPU_SH2)		:= cache-sh2.o
 cacheops-$(CONFIG_CPU_SH2A)		:= cache-sh2a.o
@@ -15,7 +15,7 @@
 
 mmu-y			:= nommu.o extable_32.o
 mmu-$(CONFIG_MMU)	:= extable_$(BITS).o fault_$(BITS).o \
-			   ioremap_$(BITS).o kmap.o tlbflush_$(BITS).o
+			   ioremap.o kmap.o pgtable.o tlbflush_$(BITS).o
 
 obj-y			+= $(mmu-y)
 obj-$(CONFIG_DEBUG_FS)	+= asids-debugfs.o
@@ -26,15 +26,17 @@
 
 ifdef CONFIG_MMU
 tlb-$(CONFIG_CPU_SH3)		:= tlb-sh3.o
-tlb-$(CONFIG_CPU_SH4)		:= tlb-sh4.o
+tlb-$(CONFIG_CPU_SH4)		:= tlb-sh4.o tlb-urb.o
 tlb-$(CONFIG_CPU_SH5)		:= tlb-sh5.o
-tlb-$(CONFIG_CPU_HAS_PTEAEX)	:= tlb-pteaex.o
+tlb-$(CONFIG_CPU_HAS_PTEAEX)	:= tlb-pteaex.o tlb-urb.o
 obj-y				+= $(tlb-y)
 endif
 
 obj-$(CONFIG_HUGETLB_PAGE)	+= hugetlbpage.o
-obj-$(CONFIG_PMB_ENABLE)	+= pmb.o
+obj-$(CONFIG_PMB)		+= pmb.o
 obj-$(CONFIG_NUMA)		+= numa.o
+obj-$(CONFIG_IOREMAP_FIXED)	+= ioremap_fixed.o
+obj-$(CONFIG_UNCACHED_MAPPING)	+= uncached.o
 
 # Special flags for fault_64.o.  This puts restrictions on the number of
 # caller-save registers that the compiler can target when building this file.
diff --git a/arch/sh/mm/alignment.c b/arch/sh/mm/alignment.c
new file mode 100644
index 0000000..b2595b8
--- /dev/null
+++ b/arch/sh/mm/alignment.c
@@ -0,0 +1,189 @@
+/*
+ * Alignment access counters and corresponding user-space interfaces.
+ *
+ * Copyright (C) 2009 ST Microelectronics
+ * Copyright (C) 2009 - 2010 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/seq_file.h>
+#include <linux/proc_fs.h>
+#include <linux/uaccess.h>
+#include <asm/alignment.h>
+#include <asm/processor.h>
+
+static unsigned long se_user;
+static unsigned long se_sys;
+static unsigned long se_half;
+static unsigned long se_word;
+static unsigned long se_dword;
+static unsigned long se_multi;
+/* bitfield: 1: warn 2: fixup 4: signal -> combinations 2|4 && 1|2|4 are not
+   valid! */
+static int se_usermode = UM_WARN | UM_FIXUP;
+/* 0: no warning 1: print a warning message, disabled by default */
+static int se_kernmode_warn;
+
+core_param(alignment, se_usermode, int, 0600);
+
+void inc_unaligned_byte_access(void)
+{
+	se_half++;
+}
+
+void inc_unaligned_word_access(void)
+{
+	se_word++;
+}
+
+void inc_unaligned_dword_access(void)
+{
+	se_dword++;
+}
+
+void inc_unaligned_multi_access(void)
+{
+	se_multi++;
+}
+
+void inc_unaligned_user_access(void)
+{
+	se_user++;
+}
+
+void inc_unaligned_kernel_access(void)
+{
+	se_sys++;
+}
+
+/*
+ * This defaults to the global policy which can be set from the command
+ * line, while processes can overload their preferences via prctl().
+ */
+unsigned int unaligned_user_action(void)
+{
+	unsigned int action = se_usermode;
+
+	if (current->thread.flags & SH_THREAD_UAC_SIGBUS) {
+		action &= ~UM_FIXUP;
+		action |= UM_SIGNAL;
+	}
+
+	if (current->thread.flags & SH_THREAD_UAC_NOPRINT)
+		action &= ~UM_WARN;
+
+	return action;
+}
+
+int get_unalign_ctl(struct task_struct *tsk, unsigned long addr)
+{
+	return put_user(tsk->thread.flags & SH_THREAD_UAC_MASK,
+			(unsigned int __user *)addr);
+}
+
+int set_unalign_ctl(struct task_struct *tsk, unsigned int val)
+{
+	tsk->thread.flags = (tsk->thread.flags & ~SH_THREAD_UAC_MASK) |
+			    (val & SH_THREAD_UAC_MASK);
+	return 0;
+}
+
+void unaligned_fixups_notify(struct task_struct *tsk, insn_size_t insn,
+			     struct pt_regs *regs)
+{
+	if (user_mode(regs) && (se_usermode & UM_WARN) && printk_ratelimit())
+		pr_notice("Fixing up unaligned userspace access "
+			  "in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n",
+			  tsk->comm, task_pid_nr(tsk),
+			  (void *)instruction_pointer(regs), insn);
+	else if (se_kernmode_warn && printk_ratelimit())
+		pr_notice("Fixing up unaligned kernel access "
+			  "in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n",
+			  tsk->comm, task_pid_nr(tsk),
+			  (void *)instruction_pointer(regs), insn);
+}
+
+static const char *se_usermode_action[] = {
+	"ignored",
+	"warn",
+	"fixup",
+	"fixup+warn",
+	"signal",
+	"signal+warn"
+};
+
+static int alignment_proc_show(struct seq_file *m, void *v)
+{
+	seq_printf(m, "User:\t\t%lu\n", se_user);
+	seq_printf(m, "System:\t\t%lu\n", se_sys);
+	seq_printf(m, "Half:\t\t%lu\n", se_half);
+	seq_printf(m, "Word:\t\t%lu\n", se_word);
+	seq_printf(m, "DWord:\t\t%lu\n", se_dword);
+	seq_printf(m, "Multi:\t\t%lu\n", se_multi);
+	seq_printf(m, "User faults:\t%i (%s)\n", se_usermode,
+			se_usermode_action[se_usermode]);
+	seq_printf(m, "Kernel faults:\t%i (fixup%s)\n", se_kernmode_warn,
+			se_kernmode_warn ? "+warn" : "");
+	return 0;
+}
+
+static int alignment_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, alignment_proc_show, NULL);
+}
+
+static ssize_t alignment_proc_write(struct file *file,
+		const char __user *buffer, size_t count, loff_t *pos)
+{
+	int *data = PDE(file->f_path.dentry->d_inode)->data;
+	char mode;
+
+	if (count > 0) {
+		if (get_user(mode, buffer))
+			return -EFAULT;
+		if (mode >= '0' && mode <= '5')
+			*data = mode - '0';
+	}
+	return count;
+}
+
+static const struct file_operations alignment_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= alignment_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+	.write		= alignment_proc_write,
+};
+
+/*
+ * This needs to be done after sysctl_init, otherwise sys/ will be
+ * overwritten.  Actually, this shouldn't be in sys/ at all since
+ * it isn't a sysctl, and it doesn't contain sysctl information.
+ * We now locate it in /proc/cpu/alignment instead.
+ */
+static int __init alignment_init(void)
+{
+	struct proc_dir_entry *dir, *res;
+
+	dir = proc_mkdir("cpu", NULL);
+	if (!dir)
+		return -ENOMEM;
+
+	res = proc_create_data("alignment", S_IWUSR | S_IRUGO, dir,
+			       &alignment_proc_fops, &se_usermode);
+	if (!res)
+		return -ENOMEM;
+
+        res = proc_create_data("kernel_alignment", S_IWUSR | S_IRUGO, dir,
+			       &alignment_proc_fops, &se_kernmode_warn);
+        if (!res)
+                return -ENOMEM;
+
+	return 0;
+}
+fs_initcall(alignment_init);
diff --git a/arch/sh/mm/cache-debugfs.c b/arch/sh/mm/cache-debugfs.c
index 5ba067b..690ed01 100644
--- a/arch/sh/mm/cache-debugfs.c
+++ b/arch/sh/mm/cache-debugfs.c
@@ -22,8 +22,7 @@
 	CACHE_TYPE_UNIFIED,
 };
 
-static int __uses_jump_to_uncached cache_seq_show(struct seq_file *file,
-						  void *iter)
+static int cache_seq_show(struct seq_file *file, void *iter)
 {
 	unsigned int cache_type = (unsigned int)file->private;
 	struct cache_info *cache;
@@ -37,7 +36,7 @@
 	 */
 	jump_to_uncached();
 
-	ccr = ctrl_inl(CCR);
+	ccr = __raw_readl(CCR);
 	if ((ccr & CCR_CACHE_ENABLE) == 0) {
 		back_to_cached();
 
@@ -90,7 +89,7 @@
 		for (addr = addrstart, line = 0;
 		     addr < addrstart + waysize;
 		     addr += cache->linesz, line++) {
-			unsigned long data = ctrl_inl(addr);
+			unsigned long data = __raw_readl(addr);
 
 			/* Check the V bit, ignore invalid cachelines */
 			if ((data & 1) == 0)
diff --git a/arch/sh/mm/cache-sh2.c b/arch/sh/mm/cache-sh2.c
index 699a71f..defcf71 100644
--- a/arch/sh/mm/cache-sh2.c
+++ b/arch/sh/mm/cache-sh2.c
@@ -28,10 +28,10 @@
 		unsigned long addr = CACHE_OC_ADDRESS_ARRAY | (v & 0x00000ff0);
 		int way;
 		for (way = 0; way < 4; way++) {
-			unsigned long data =  ctrl_inl(addr | (way << 12));
+			unsigned long data =  __raw_readl(addr | (way << 12));
 			if ((data & CACHE_PHYSADDR_MASK) == (v & CACHE_PHYSADDR_MASK)) {
 				data &= ~SH_CACHE_UPDATED;
-				ctrl_outl(data, addr | (way << 12));
+				__raw_writel(data, addr | (way << 12));
 			}
 		}
 	}
@@ -47,7 +47,7 @@
 		& ~(L1_CACHE_BYTES-1);
 
 	for (v = begin; v < end; v+=L1_CACHE_BYTES)
-		ctrl_outl((v & CACHE_PHYSADDR_MASK),
+		__raw_writel((v & CACHE_PHYSADDR_MASK),
 			  CACHE_OC_ADDRESS_ARRAY | (v & 0x00000ff0) | 0x00000008);
 }
 
@@ -63,9 +63,9 @@
 	local_irq_save(flags);
 	jump_to_uncached();
 
-	ccr = ctrl_inl(CCR);
+	ccr = __raw_readl(CCR);
 	ccr |= CCR_CACHE_INVALIDATE;
-	ctrl_outl(ccr, CCR);
+	__raw_writel(ccr, CCR);
 
 	back_to_cached();
 	local_irq_restore(flags);
@@ -78,7 +78,7 @@
 		& ~(L1_CACHE_BYTES-1);
 
 	for (v = begin; v < end; v+=L1_CACHE_BYTES)
-		ctrl_outl((v & CACHE_PHYSADDR_MASK),
+		__raw_writel((v & CACHE_PHYSADDR_MASK),
 			  CACHE_OC_ADDRESS_ARRAY | (v & 0x00000ff0) | 0x00000008);
 #endif
 }
diff --git a/arch/sh/mm/cache-sh2a.c b/arch/sh/mm/cache-sh2a.c
index 975899d..1f51225 100644
--- a/arch/sh/mm/cache-sh2a.c
+++ b/arch/sh/mm/cache-sh2a.c
@@ -32,10 +32,10 @@
 		unsigned long addr = CACHE_OC_ADDRESS_ARRAY | (v & 0x000007f0);
 		int way;
 		for (way = 0; way < 4; way++) {
-			unsigned long data =  ctrl_inl(addr | (way << 11));
+			unsigned long data =  __raw_readl(addr | (way << 11));
 			if ((data & CACHE_PHYSADDR_MASK) == (v & CACHE_PHYSADDR_MASK)) {
 				data &= ~SH_CACHE_UPDATED;
-				ctrl_outl(data, addr | (way << 11));
+				__raw_writel(data, addr | (way << 11));
 			}
 		}
 	}
@@ -58,7 +58,7 @@
 	jump_to_uncached();
 
 	for (v = begin; v < end; v+=L1_CACHE_BYTES) {
-		ctrl_outl((v & CACHE_PHYSADDR_MASK),
+		__raw_writel((v & CACHE_PHYSADDR_MASK),
 			  CACHE_OC_ADDRESS_ARRAY | (v & 0x000007f0) | 0x00000008);
 	}
 	back_to_cached();
@@ -78,17 +78,17 @@
 	jump_to_uncached();
 
 #ifdef CONFIG_CACHE_WRITEBACK
-	ctrl_outl(ctrl_inl(CCR) | CCR_OCACHE_INVALIDATE, CCR);
+	__raw_writel(__raw_readl(CCR) | CCR_OCACHE_INVALIDATE, CCR);
 	/* I-cache invalidate */
 	for (v = begin; v < end; v+=L1_CACHE_BYTES) {
-		ctrl_outl((v & CACHE_PHYSADDR_MASK),
+		__raw_writel((v & CACHE_PHYSADDR_MASK),
 			  CACHE_IC_ADDRESS_ARRAY | (v & 0x000007f0) | 0x00000008);
 	}
 #else
 	for (v = begin; v < end; v+=L1_CACHE_BYTES) {
-		ctrl_outl((v & CACHE_PHYSADDR_MASK),
+		__raw_writel((v & CACHE_PHYSADDR_MASK),
 			  CACHE_IC_ADDRESS_ARRAY | (v & 0x000007f0) | 0x00000008);
-		ctrl_outl((v & CACHE_PHYSADDR_MASK),
+		__raw_writel((v & CACHE_PHYSADDR_MASK),
 			  CACHE_OC_ADDRESS_ARRAY | (v & 0x000007f0) | 0x00000008);
 	}
 #endif
@@ -115,14 +115,14 @@
 		int way;
 		/* O-Cache writeback */
 		for (way = 0; way < 4; way++) {
-			unsigned long data =  ctrl_inl(CACHE_OC_ADDRESS_ARRAY | addr | (way << 11));
+			unsigned long data =  __raw_readl(CACHE_OC_ADDRESS_ARRAY | addr | (way << 11));
 			if ((data & CACHE_PHYSADDR_MASK) == (v & CACHE_PHYSADDR_MASK)) {
 				data &= ~SH_CACHE_UPDATED;
-				ctrl_outl(data, CACHE_OC_ADDRESS_ARRAY | addr | (way << 11));
+				__raw_writel(data, CACHE_OC_ADDRESS_ARRAY | addr | (way << 11));
 			}
 		}
 		/* I-Cache invalidate */
-		ctrl_outl(addr,
+		__raw_writel(addr,
 			  CACHE_IC_ADDRESS_ARRAY | addr | 0x00000008);
 	}
 
diff --git a/arch/sh/mm/cache-sh3.c b/arch/sh/mm/cache-sh3.c
index faef80c..e37523f 100644
--- a/arch/sh/mm/cache-sh3.c
+++ b/arch/sh/mm/cache-sh3.c
@@ -50,12 +50,12 @@
 			p = __pa(v);
 			addr = addrstart | (v & current_cpu_data.dcache.entry_mask);
 			local_irq_save(flags);
-			data = ctrl_inl(addr);
+			data = __raw_readl(addr);
 
 			if ((data & CACHE_PHYSADDR_MASK) ==
 			    (p & CACHE_PHYSADDR_MASK)) {
 				data &= ~SH_CACHE_UPDATED;
-				ctrl_outl(data, addr);
+				__raw_writel(data, addr);
 				local_irq_restore(flags);
 				break;
 			}
@@ -86,7 +86,7 @@
 		data = (v & 0xfffffc00); /* _Virtual_ address, ~U, ~V */
 		addr = CACHE_OC_ADDRESS_ARRAY |
 			(v & current_cpu_data.dcache.entry_mask) | SH_CACHE_ASSOC;
-		ctrl_outl(data, addr);
+		__raw_writel(data, addr);
 	}
 }
 
diff --git a/arch/sh/mm/cache-sh4.c b/arch/sh/mm/cache-sh4.c
index 560ddb6..2cfae81 100644
--- a/arch/sh/mm/cache-sh4.c
+++ b/arch/sh/mm/cache-sh4.c
@@ -36,7 +36,7 @@
  * Called from kernel/module.c:sys_init_module and routine for a.out format,
  * signal handler code and kprobes code
  */
-static void __uses_jump_to_uncached sh4_flush_icache_range(void *args)
+static void sh4_flush_icache_range(void *args)
 {
 	struct flusher_data *data = args;
 	unsigned long start, end;
@@ -109,6 +109,7 @@
 static void sh4_flush_dcache_page(void *arg)
 {
 	struct page *page = arg;
+	unsigned long addr = (unsigned long)page_address(page);
 #ifndef CONFIG_SMP
 	struct address_space *mapping = page_mapping(page);
 
@@ -116,22 +117,14 @@
 		set_bit(PG_dcache_dirty, &page->flags);
 	else
 #endif
-	{
-		unsigned long phys = page_to_phys(page);
-		unsigned long addr = CACHE_OC_ADDRESS_ARRAY;
-		int i, n;
-
-		/* Loop all the D-cache */
-		n = boot_cpu_data.dcache.n_aliases;
-		for (i = 0; i < n; i++, addr += PAGE_SIZE)
-			flush_cache_one(addr, phys);
-	}
+		flush_cache_one(CACHE_OC_ADDRESS_ARRAY |
+				(addr & shm_align_mask), page_to_phys(page));
 
 	wmb();
 }
 
 /* TODO: Selective icache invalidation through IC address array.. */
-static void __uses_jump_to_uncached flush_icache_all(void)
+static void flush_icache_all(void)
 {
 	unsigned long flags, ccr;
 
@@ -139,9 +132,9 @@
 	jump_to_uncached();
 
 	/* Flush I-cache */
-	ccr = ctrl_inl(CCR);
+	ccr = __raw_readl(CCR);
 	ccr |= CCR_CACHE_ICI;
-	ctrl_outl(ccr, CCR);
+	__raw_writel(ccr, CCR);
 
 	/*
 	 * back_to_cached() will take care of the barrier for us, don't add
@@ -384,9 +377,9 @@
 void __init sh4_cache_init(void)
 {
 	printk("PVR=%08x CVR=%08x PRR=%08x\n",
-		ctrl_inl(CCN_PVR),
-		ctrl_inl(CCN_CVR),
-		ctrl_inl(CCN_PRR));
+		__raw_readl(CCN_PVR),
+		__raw_readl(CCN_CVR),
+		__raw_readl(CCN_PRR));
 
 	local_flush_icache_range	= sh4_flush_icache_range;
 	local_flush_dcache_page		= sh4_flush_dcache_page;
diff --git a/arch/sh/mm/cache-sh7705.c b/arch/sh/mm/cache-sh7705.c
index f527fb7..f498da1 100644
--- a/arch/sh/mm/cache-sh7705.c
+++ b/arch/sh/mm/cache-sh7705.c
@@ -48,10 +48,10 @@
 			unsigned long data;
 			int v = SH_CACHE_UPDATED | SH_CACHE_VALID;
 
-			data = ctrl_inl(addr);
+			data = __raw_readl(addr);
 
 			if ((data & v) == v)
-				ctrl_outl(data & ~v, addr);
+				__raw_writel(data & ~v, addr);
 
 		}
 
@@ -78,7 +78,7 @@
 /*
  * Writeback&Invalidate the D-cache of the page
  */
-static void __uses_jump_to_uncached __flush_dcache_page(unsigned long phys)
+static void __flush_dcache_page(unsigned long phys)
 {
 	unsigned long ways, waysize, addrstart;
 	unsigned long flags;
@@ -115,10 +115,10 @@
 		     addr += current_cpu_data.dcache.linesz) {
 			unsigned long data;
 
-			data = ctrl_inl(addr) & (0x1ffffC00 | SH_CACHE_VALID);
+			data = __raw_readl(addr) & (0x1ffffC00 | SH_CACHE_VALID);
 		        if (data == phys) {
 				data &= ~(SH_CACHE_VALID | SH_CACHE_UPDATED);
-				ctrl_outl(data, addr);
+				__raw_writel(data, addr);
 			}
 		}
 
@@ -144,7 +144,7 @@
 		__flush_dcache_page(__pa(page_address(page)));
 }
 
-static void __uses_jump_to_uncached sh7705_flush_cache_all(void *args)
+static void sh7705_flush_cache_all(void *args)
 {
 	unsigned long flags;
 
diff --git a/arch/sh/mm/cache.c b/arch/sh/mm/cache.c
index b8607fa..0f4095d 100644
--- a/arch/sh/mm/cache.c
+++ b/arch/sh/mm/cache.c
@@ -2,7 +2,7 @@
  * arch/sh/mm/cache.c
  *
  * Copyright (C) 1999, 2000, 2002  Niibe Yutaka
- * Copyright (C) 2002 - 2009  Paul Mundt
+ * Copyright (C) 2002 - 2010  Paul Mundt
  *
  * Released under the terms of the GNU GPL v2.0.
  */
@@ -41,8 +41,17 @@
                                    int wait)
 {
 	preempt_disable();
-	smp_call_function(func, info, wait);
+
+	/*
+	 * It's possible that this gets called early on when IRQs are
+	 * still disabled due to ioremapping by the boot CPU, so don't
+	 * even attempt IPIs unless there are other CPUs online.
+	 */
+	if (num_online_cpus() > 1)
+		smp_call_function(func, info, wait);
+
 	func(info);
+
 	preempt_enable();
 }
 
diff --git a/arch/sh/mm/fault_32.c b/arch/sh/mm/fault_32.c
index 4753010..28e2283 100644
--- a/arch/sh/mm/fault_32.c
+++ b/arch/sh/mm/fault_32.c
@@ -53,6 +53,9 @@
 	if (!pud_present(*pud_k))
 		return NULL;
 
+	if (!pud_present(*pud))
+	    set_pud(pud, *pud_k);
+
 	pmd = pmd_offset(pud, address);
 	pmd_k = pmd_offset(pud_k, address);
 	if (!pmd_present(*pmd_k))
diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c
index 432acd0..68028e8 100644
--- a/arch/sh/mm/init.c
+++ b/arch/sh/mm/init.c
@@ -21,25 +21,13 @@
 #include <asm/cacheflush.h>
 #include <asm/sections.h>
 #include <asm/cache.h>
+#include <asm/sizes.h>
 
 DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 pgd_t swapper_pg_dir[PTRS_PER_PGD];
 
-#ifdef CONFIG_SUPERH32
-/*
- * Handle trivial transitions between cached and uncached
- * segments, making use of the 1:1 mapping relationship in
- * 512MB lowmem.
- *
- * This is the offset of the uncached section from its cached alias.
- * Default value only valid in 29 bit mode, in 32bit mode will be
- * overridden in pmb_init.
- */
-unsigned long cached_to_uncached = P2SEG - P1SEG;
-#endif
-
 #ifdef CONFIG_MMU
-static void set_pte_phys(unsigned long addr, unsigned long phys, pgprot_t prot)
+static pte_t *__get_pte_phys(unsigned long addr)
 {
 	pgd_t *pgd;
 	pud_t *pud;
@@ -49,22 +37,30 @@
 	pgd = pgd_offset_k(addr);
 	if (pgd_none(*pgd)) {
 		pgd_ERROR(*pgd);
-		return;
+		return NULL;
 	}
 
 	pud = pud_alloc(NULL, pgd, addr);
 	if (unlikely(!pud)) {
 		pud_ERROR(*pud);
-		return;
+		return NULL;
 	}
 
 	pmd = pmd_alloc(NULL, pud, addr);
 	if (unlikely(!pmd)) {
 		pmd_ERROR(*pmd);
-		return;
+		return NULL;
 	}
 
 	pte = pte_offset_kernel(pmd, addr);
+	return pte;
+}
+
+static void set_pte_phys(unsigned long addr, unsigned long phys, pgprot_t prot)
+{
+	pte_t *pte;
+
+	pte = __get_pte_phys(addr);
 	if (!pte_none(*pte)) {
 		pte_ERROR(*pte);
 		return;
@@ -72,23 +68,24 @@
 
 	set_pte(pte, pfn_pte(phys >> PAGE_SHIFT, prot));
 	local_flush_tlb_one(get_asid(), addr);
+
+	if (pgprot_val(prot) & _PAGE_WIRED)
+		tlb_wire_entry(NULL, addr, *pte);
 }
 
-/*
- * As a performance optimization, other platforms preserve the fixmap mapping
- * across a context switch, we don't presently do this, but this could be done
- * in a similar fashion as to the wired TLB interface that sh64 uses (by way
- * of the memory mapped UTLB configuration) -- this unfortunately forces us to
- * give up a TLB entry for each mapping we want to preserve. While this may be
- * viable for a small number of fixmaps, it's not particularly useful for
- * everything and needs to be carefully evaluated. (ie, we may want this for
- * the vsyscall page).
- *
- * XXX: Perhaps add a _PAGE_WIRED flag or something similar that we can pass
- * in at __set_fixmap() time to determine the appropriate behavior to follow.
- *
- *					 -- PFM.
- */
+static void clear_pte_phys(unsigned long addr, pgprot_t prot)
+{
+	pte_t *pte;
+
+	pte = __get_pte_phys(addr);
+
+	if (pgprot_val(prot) & _PAGE_WIRED)
+		tlb_unwire_entry();
+
+	set_pte(pte, pfn_pte(0, __pgprot(0)));
+	local_flush_tlb_one(get_asid(), addr);
+}
+
 void __set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t prot)
 {
 	unsigned long address = __fix_to_virt(idx);
@@ -101,6 +98,18 @@
 	set_pte_phys(address, phys, prot);
 }
 
+void __clear_fixmap(enum fixed_addresses idx, pgprot_t prot)
+{
+	unsigned long address = __fix_to_virt(idx);
+
+	if (idx >= __end_of_fixed_addresses) {
+		BUG();
+		return;
+	}
+
+	clear_pte_phys(address, prot);
+}
+
 void __init page_table_range_init(unsigned long start, unsigned long end,
 					 pgd_t *pgd_base)
 {
@@ -120,7 +129,13 @@
 	for ( ; (i < PTRS_PER_PGD) && (vaddr != end); pgd++, i++) {
 		pud = (pud_t *)pgd;
 		for ( ; (j < PTRS_PER_PUD) && (vaddr != end); pud++, j++) {
+#ifdef __PAGETABLE_PMD_FOLDED
 			pmd = (pmd_t *)pud;
+#else
+			pmd = (pmd_t *)alloc_bootmem_low_pages(PAGE_SIZE);
+			pud_populate(&init_mm, pud, pmd);
+			pmd += k;
+#endif
 			for (; (k < PTRS_PER_PMD) && (vaddr != end); pmd++, k++) {
 				if (pmd_none(*pmd)) {
 					pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
@@ -182,9 +197,6 @@
 	}
 
 	free_area_init_nodes(max_zone_pfns);
-
-	/* Set up the uncached fixmap */
-	set_fixmap_nocache(FIX_UNCACHED, __pa(&__uncached_start));
 }
 
 /*
@@ -195,6 +207,8 @@
 	no_iommu_init();
 }
 
+unsigned int mem_init_done = 0;
+
 void __init mem_init(void)
 {
 	int codesize, datasize, initsize;
@@ -231,6 +245,8 @@
 	memset(empty_zero_page, 0, PAGE_SIZE);
 	__flush_wback_region(empty_zero_page, PAGE_SIZE);
 
+	vsyscall_init();
+
 	codesize =  (unsigned long) &_etext - (unsigned long) &_text;
 	datasize =  (unsigned long) &_edata - (unsigned long) &_etext;
 	initsize =  (unsigned long) &__init_end - (unsigned long) &__init_begin;
@@ -243,8 +259,48 @@
 		datasize >> 10,
 		initsize >> 10);
 
-	/* Initialize the vDSO */
-	vsyscall_init();
+	printk(KERN_INFO "virtual kernel memory layout:\n"
+		"    fixmap  : 0x%08lx - 0x%08lx   (%4ld kB)\n"
+#ifdef CONFIG_HIGHMEM
+		"    pkmap   : 0x%08lx - 0x%08lx   (%4ld kB)\n"
+#endif
+		"    vmalloc : 0x%08lx - 0x%08lx   (%4ld MB)\n"
+		"    lowmem  : 0x%08lx - 0x%08lx   (%4ld MB) (cached)\n"
+#ifdef CONFIG_UNCACHED_MAPPING
+		"            : 0x%08lx - 0x%08lx   (%4ld MB) (uncached)\n"
+#endif
+		"      .init : 0x%08lx - 0x%08lx   (%4ld kB)\n"
+		"      .data : 0x%08lx - 0x%08lx   (%4ld kB)\n"
+		"      .text : 0x%08lx - 0x%08lx   (%4ld kB)\n",
+		FIXADDR_START, FIXADDR_TOP,
+		(FIXADDR_TOP - FIXADDR_START) >> 10,
+
+#ifdef CONFIG_HIGHMEM
+		PKMAP_BASE, PKMAP_BASE+LAST_PKMAP*PAGE_SIZE,
+		(LAST_PKMAP*PAGE_SIZE) >> 10,
+#endif
+
+		(unsigned long)VMALLOC_START, VMALLOC_END,
+		(VMALLOC_END - VMALLOC_START) >> 20,
+
+		(unsigned long)memory_start, (unsigned long)high_memory,
+		((unsigned long)high_memory - (unsigned long)memory_start) >> 20,
+
+#ifdef CONFIG_UNCACHED_MAPPING
+		uncached_start, uncached_end, uncached_size >> 20,
+#endif
+
+		(unsigned long)&__init_begin, (unsigned long)&__init_end,
+		((unsigned long)&__init_end -
+		 (unsigned long)&__init_begin) >> 10,
+
+		(unsigned long)&_etext, (unsigned long)&_edata,
+		((unsigned long)&_edata - (unsigned long)&_etext) >> 10,
+
+		(unsigned long)&_text, (unsigned long)&_etext,
+		((unsigned long)&_etext - (unsigned long)&_text) >> 10);
+
+	mem_init_done = 1;
 }
 
 void free_initmem(void)
@@ -277,35 +333,6 @@
 }
 #endif
 
-#if THREAD_SHIFT < PAGE_SHIFT
-static struct kmem_cache *thread_info_cache;
-
-struct thread_info *alloc_thread_info(struct task_struct *tsk)
-{
-	struct thread_info *ti;
-
-	ti = kmem_cache_alloc(thread_info_cache, GFP_KERNEL);
-	if (unlikely(ti == NULL))
-		return NULL;
-#ifdef CONFIG_DEBUG_STACK_USAGE
-	memset(ti, 0, THREAD_SIZE);
-#endif
-	return ti;
-}
-
-void free_thread_info(struct thread_info *ti)
-{
-	kmem_cache_free(thread_info_cache, ti);
-}
-
-void thread_info_cache_init(void)
-{
-	thread_info_cache = kmem_cache_create("thread_info", THREAD_SIZE,
-					      THREAD_SIZE, 0, NULL);
-	BUG_ON(thread_info_cache == NULL);
-}
-#endif /* THREAD_SHIFT < PAGE_SHIFT */
-
 #ifdef CONFIG_MEMORY_HOTPLUG
 int arch_add_memory(int nid, u64 start, u64 size)
 {
@@ -336,10 +363,3 @@
 #endif
 
 #endif /* CONFIG_MEMORY_HOTPLUG */
-
-#ifdef CONFIG_PMB
-int __in_29bit_mode(void)
-{
-	return !(ctrl_inl(PMB_PASCR) & PASCR_SE);
-}
-#endif /* CONFIG_PMB */
diff --git a/arch/sh/mm/ioremap_32.c b/arch/sh/mm/ioremap.c
similarity index 78%
rename from arch/sh/mm/ioremap_32.c
rename to arch/sh/mm/ioremap.c
index 2141bef..c68d2d7 100644
--- a/arch/sh/mm/ioremap_32.c
+++ b/arch/sh/mm/ioremap.c
@@ -1,13 +1,13 @@
 /*
  * arch/sh/mm/ioremap.c
  *
+ * (C) Copyright 1995 1996 Linus Torvalds
+ * (C) Copyright 2005 - 2010  Paul Mundt
+ *
  * Re-map IO memory to kernel address space so that we can access it.
  * This is needed for high PCI addresses that aren't mapped in the
  * 640k-1MB IO memory area on PC's
  *
- * (C) Copyright 1995 1996 Linus Torvalds
- * (C) Copyright 2005, 2006 Paul Mundt
- *
  * This file is subject to the terms and conditions of the GNU General
  * Public License. See the file "COPYING" in the main directory of this
  * archive for more details.
@@ -33,12 +33,12 @@
  * have to convert them into an offset in a page-aligned mapping, but the
  * caller shouldn't need to know that small detail.
  */
-void __iomem *__ioremap_caller(unsigned long phys_addr, unsigned long size,
-			       unsigned long flags, void *caller)
+void __iomem * __init_refok
+__ioremap_caller(unsigned long phys_addr, unsigned long size,
+		 pgprot_t pgprot, void *caller)
 {
 	struct vm_struct *area;
 	unsigned long offset, last_addr, addr, orig_addr;
-	pgprot_t pgprot;
 
 	/* Don't allow wraparound or zero size */
 	last_addr = phys_addr + size - 1;
@@ -46,18 +46,6 @@
 		return NULL;
 
 	/*
-	 * If we're in the fixed PCI memory range, mapping through page
-	 * tables is not only pointless, but also fundamentally broken.
-	 * Just return the physical address instead.
-	 *
-	 * For boards that map a small PCI memory aperture somewhere in
-	 * P1/P2 space, ioremap() will already do the right thing,
-	 * and we'll never get this far.
-	 */
-	if (is_pci_memory_fixed_range(phys_addr, size))
-		return (void __iomem *)phys_addr;
-
-	/*
 	 * Mappings have to be page-aligned
 	 */
 	offset = phys_addr & ~PAGE_MASK;
@@ -65,6 +53,12 @@
 	size = PAGE_ALIGN(last_addr+1) - phys_addr;
 
 	/*
+	 * If we can't yet use the regular approach, go the fixmap route.
+	 */
+	if (!mem_init_done)
+		return ioremap_fixed(phys_addr, offset, size, pgprot);
+
+	/*
 	 * Ok, go for it..
 	 */
 	area = get_vm_area_caller(size, VM_IOREMAP, caller);
@@ -84,8 +78,9 @@
 	 * PMB entries are all pre-faulted.
 	 */
 	if (unlikely(phys_addr >= P1SEG)) {
-		unsigned long mapped = pmb_remap(addr, phys_addr, size, flags);
+		unsigned long mapped;
 
+		mapped = pmb_remap(addr, phys_addr, size, pgprot);
 		if (likely(mapped)) {
 			addr		+= mapped;
 			phys_addr	+= mapped;
@@ -94,7 +89,6 @@
 	}
 #endif
 
-	pgprot = __pgprot(pgprot_val(PAGE_KERNEL_NOCACHE) | flags);
 	if (likely(size))
 		if (ioremap_page_range(addr, addr + size, phys_addr, pgprot)) {
 			vunmap((void *)orig_addr);
@@ -105,15 +99,38 @@
 }
 EXPORT_SYMBOL(__ioremap_caller);
 
+/*
+ * Simple checks for non-translatable mappings.
+ */
+static inline int iomapping_nontranslatable(unsigned long offset)
+{
+#ifdef CONFIG_29BIT
+	/*
+	 * In 29-bit mode this includes the fixed P1/P2 areas, as well as
+	 * parts of P3.
+	 */
+	if (PXSEG(offset) < P3SEG || offset >= P3_ADDR_MAX)
+		return 1;
+#endif
+
+	return 0;
+}
+
 void __iounmap(void __iomem *addr)
 {
 	unsigned long vaddr = (unsigned long __force)addr;
-	unsigned long seg = PXSEG(vaddr);
 	struct vm_struct *p;
 
-	if (seg < P3SEG || vaddr >= P3_ADDR_MAX)
+	/*
+	 * Nothing to do if there is no translatable mapping.
+	 */
+	if (iomapping_nontranslatable(vaddr))
 		return;
-	if (is_pci_memory_fixed_range(vaddr, 0))
+
+	/*
+	 * There's no VMA if it's from an early fixed mapping.
+	 */
+	if (iounmap_fixed(addr) == 0)
 		return;
 
 #ifdef CONFIG_PMB
diff --git a/arch/sh/mm/ioremap_64.c b/arch/sh/mm/ioremap_64.c
deleted file mode 100644
index ef43465..0000000
--- a/arch/sh/mm/ioremap_64.c
+++ /dev/null
@@ -1,326 +0,0 @@
-/*
- * arch/sh/mm/ioremap_64.c
- *
- * Copyright (C) 2000, 2001  Paolo Alberelli
- * Copyright (C) 2003 - 2007  Paul Mundt
- *
- * Mostly derived from arch/sh/mm/ioremap.c which, in turn is mostly
- * derived from arch/i386/mm/ioremap.c .
- *
- *   (C) Copyright 1995 1996 Linus Torvalds
- *
- * 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/vmalloc.h>
-#include <linux/ioport.h>
-#include <linux/module.h>
-#include <linux/mm.h>
-#include <linux/io.h>
-#include <linux/bootmem.h>
-#include <linux/proc_fs.h>
-#include <linux/slab.h>
-#include <asm/page.h>
-#include <asm/pgalloc.h>
-#include <asm/addrspace.h>
-#include <asm/cacheflush.h>
-#include <asm/tlbflush.h>
-#include <asm/mmu.h>
-
-static struct resource shmedia_iomap = {
-	.name	= "shmedia_iomap",
-	.start	= IOBASE_VADDR + PAGE_SIZE,
-	.end	= IOBASE_END - 1,
-};
-
-static void shmedia_mapioaddr(unsigned long pa, unsigned long va,
-			      unsigned long flags);
-static void shmedia_unmapioaddr(unsigned long vaddr);
-static void __iomem *shmedia_ioremap(struct resource *res, u32 pa,
-				     int sz, unsigned long flags);
-
-/*
- * We have the same problem as the SPARC, so lets have the same comment:
- * Our mini-allocator...
- * Boy this is gross! We need it because we must map I/O for
- * timers and interrupt controller before the kmalloc is available.
- */
-
-#define XNMLN  15
-#define XNRES  10
-
-struct xresource {
-	struct resource xres;   /* Must be first */
-	int xflag;              /* 1 == used */
-	char xname[XNMLN+1];
-};
-
-static struct xresource xresv[XNRES];
-
-static struct xresource *xres_alloc(void)
-{
-	struct xresource *xrp;
-	int n;
-
-	xrp = xresv;
-	for (n = 0; n < XNRES; n++) {
-		if (xrp->xflag == 0) {
-			xrp->xflag = 1;
-			return xrp;
-		}
-		xrp++;
-	}
-	return NULL;
-}
-
-static void xres_free(struct xresource *xrp)
-{
-	xrp->xflag = 0;
-}
-
-static struct resource *shmedia_find_resource(struct resource *root,
-					      unsigned long vaddr)
-{
-	struct resource *res;
-
-	for (res = root->child; res; res = res->sibling)
-		if (res->start <= vaddr && res->end >= vaddr)
-			return res;
-
-	return NULL;
-}
-
-static void __iomem *shmedia_alloc_io(unsigned long phys, unsigned long size,
-				      const char *name, unsigned long flags)
-{
-	struct xresource *xres;
-	struct resource *res;
-	char *tack;
-	int tlen;
-
-	if (name == NULL)
-		name = "???";
-
-	xres = xres_alloc();
-	if (xres != 0) {
-		tack = xres->xname;
-		res = &xres->xres;
-	} else {
-		printk_once(KERN_NOTICE "%s: done with statics, "
-			       "switching to kmalloc\n", __func__);
-		tlen = strlen(name);
-		tack = kmalloc(sizeof(struct resource) + tlen + 1, GFP_KERNEL);
-		if (!tack)
-			return NULL;
-		memset(tack, 0, sizeof(struct resource));
-		res = (struct resource *) tack;
-		tack += sizeof(struct resource);
-	}
-
-	strncpy(tack, name, XNMLN);
-	tack[XNMLN] = 0;
-	res->name = tack;
-
-	return shmedia_ioremap(res, phys, size, flags);
-}
-
-static void __iomem *shmedia_ioremap(struct resource *res, u32 pa, int sz,
-				     unsigned long flags)
-{
-	unsigned long offset = ((unsigned long) pa) & (~PAGE_MASK);
-	unsigned long round_sz = (offset + sz + PAGE_SIZE-1) & PAGE_MASK;
-	unsigned long va;
-	unsigned int psz;
-
-	if (allocate_resource(&shmedia_iomap, res, round_sz,
-			      shmedia_iomap.start, shmedia_iomap.end,
-			      PAGE_SIZE, NULL, NULL) != 0) {
-		panic("alloc_io_res(%s): cannot occupy\n",
-		      (res->name != NULL) ? res->name : "???");
-	}
-
-	va = res->start;
-	pa &= PAGE_MASK;
-
-	psz = (res->end - res->start + (PAGE_SIZE - 1)) / PAGE_SIZE;
-
-	for (psz = res->end - res->start + 1; psz != 0; psz -= PAGE_SIZE) {
-		shmedia_mapioaddr(pa, va, flags);
-		va += PAGE_SIZE;
-		pa += PAGE_SIZE;
-	}
-
-	return (void __iomem *)(unsigned long)(res->start + offset);
-}
-
-static void shmedia_free_io(struct resource *res)
-{
-	unsigned long len = res->end - res->start + 1;
-
-	BUG_ON((len & (PAGE_SIZE - 1)) != 0);
-
-	while (len) {
-		len -= PAGE_SIZE;
-		shmedia_unmapioaddr(res->start + len);
-	}
-
-	release_resource(res);
-}
-
-static __init_refok void *sh64_get_page(void)
-{
-	void *page;
-
-	if (slab_is_available())
-		page = (void *)get_zeroed_page(GFP_KERNEL);
-	else
-		page = alloc_bootmem_pages(PAGE_SIZE);
-
-	if (!page || ((unsigned long)page & ~PAGE_MASK))
-		panic("sh64_get_page: Out of memory already?\n");
-
-	return page;
-}
-
-static void shmedia_mapioaddr(unsigned long pa, unsigned long va,
-			      unsigned long flags)
-{
-	pgd_t *pgdp;
-	pud_t *pudp;
-	pmd_t *pmdp;
-	pte_t *ptep, pte;
-	pgprot_t prot;
-
-	pr_debug("shmedia_mapiopage pa %08lx va %08lx\n",  pa, va);
-
-	if (!flags)
-		flags = 1; /* 1 = CB0-1 device */
-
-	pgdp = pgd_offset_k(va);
-	if (pgd_none(*pgdp) || !pgd_present(*pgdp)) {
-		pudp = (pud_t *)sh64_get_page();
-		set_pgd(pgdp, __pgd((unsigned long)pudp | _KERNPG_TABLE));
-	}
-
-	pudp = pud_offset(pgdp, va);
-	if (pud_none(*pudp) || !pud_present(*pudp)) {
-		pmdp = (pmd_t *)sh64_get_page();
-		set_pud(pudp, __pud((unsigned long)pmdp | _KERNPG_TABLE));
-	}
-
-	pmdp = pmd_offset(pudp, va);
-	if (pmd_none(*pmdp) || !pmd_present(*pmdp)) {
-		ptep = (pte_t *)sh64_get_page();
-		set_pmd(pmdp, __pmd((unsigned long)ptep + _PAGE_TABLE));
-	}
-
-	prot = __pgprot(_PAGE_PRESENT | _PAGE_READ     | _PAGE_WRITE  |
-			_PAGE_DIRTY   | _PAGE_ACCESSED | _PAGE_SHARED | flags);
-
-	pte = pfn_pte(pa >> PAGE_SHIFT, prot);
-	ptep = pte_offset_kernel(pmdp, va);
-
-	if (!pte_none(*ptep) &&
-	    pte_val(*ptep) != pte_val(pte))
-		pte_ERROR(*ptep);
-
-	set_pte(ptep, pte);
-
-	flush_tlb_kernel_range(va, PAGE_SIZE);
-}
-
-static void shmedia_unmapioaddr(unsigned long vaddr)
-{
-	pgd_t *pgdp;
-	pud_t *pudp;
-	pmd_t *pmdp;
-	pte_t *ptep;
-
-	pgdp = pgd_offset_k(vaddr);
-	if (pgd_none(*pgdp) || pgd_bad(*pgdp))
-		return;
-
-	pudp = pud_offset(pgdp, vaddr);
-	if (pud_none(*pudp) || pud_bad(*pudp))
-		return;
-
-	pmdp = pmd_offset(pudp, vaddr);
-	if (pmd_none(*pmdp) || pmd_bad(*pmdp))
-		return;
-
-	ptep = pte_offset_kernel(pmdp, vaddr);
-
-	if (pte_none(*ptep) || !pte_present(*ptep))
-		return;
-
-	clear_page((void *)ptep);
-	pte_clear(&init_mm, vaddr, ptep);
-}
-
-void __iomem *__ioremap_caller(unsigned long offset, unsigned long size,
-			       unsigned long flags, void *caller)
-{
-	char name[14];
-
-	sprintf(name, "phys_%08x", (u32)offset);
-	return shmedia_alloc_io(offset, size, name, flags);
-}
-EXPORT_SYMBOL(__ioremap_caller);
-
-void __iounmap(void __iomem *virtual)
-{
-	unsigned long vaddr = (unsigned long)virtual & PAGE_MASK;
-	struct resource *res;
-	unsigned int psz;
-
-	res = shmedia_find_resource(&shmedia_iomap, vaddr);
-	if (!res) {
-		printk(KERN_ERR "%s: Failed to free 0x%08lx\n",
-		       __func__, vaddr);
-		return;
-	}
-
-	psz = (res->end - res->start + (PAGE_SIZE - 1)) / PAGE_SIZE;
-
-	shmedia_free_io(res);
-
-	if ((char *)res >= (char *)xresv &&
-	    (char *)res <  (char *)&xresv[XNRES]) {
-		xres_free((struct xresource *)res);
-	} else {
-		kfree(res);
-	}
-}
-EXPORT_SYMBOL(__iounmap);
-
-static int
-ioremap_proc_info(char *buf, char **start, off_t fpos, int length, int *eof,
-		  void *data)
-{
-	char *p = buf, *e = buf + length;
-	struct resource *r;
-	const char *nm;
-
-	for (r = ((struct resource *)data)->child; r != NULL; r = r->sibling) {
-		if (p + 32 >= e)        /* Better than nothing */
-			break;
-		nm = r->name;
-		if (nm == NULL)
-			nm = "???";
-
-		p += sprintf(p, "%08lx-%08lx: %s\n",
-			     (unsigned long)r->start,
-			     (unsigned long)r->end, nm);
-	}
-
-	return p-buf;
-}
-
-static int __init register_proc_onchip(void)
-{
-	create_proc_read_entry("io_map", 0, 0, ioremap_proc_info,
-			       &shmedia_iomap);
-	return 0;
-}
-late_initcall(register_proc_onchip);
diff --git a/arch/sh/mm/ioremap_fixed.c b/arch/sh/mm/ioremap_fixed.c
new file mode 100644
index 0000000..0b78b1e
--- /dev/null
+++ b/arch/sh/mm/ioremap_fixed.c
@@ -0,0 +1,128 @@
+/*
+ * Re-map IO memory to kernel address space so that we can access it.
+ *
+ * These functions should only be used when it is necessary to map a
+ * physical address space into the kernel address space before ioremap()
+ * can be used, e.g. early in boot before paging_init().
+ *
+ * Copyright (C) 2009  Matt Fleming
+ */
+
+#include <linux/vmalloc.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/io.h>
+#include <linux/bootmem.h>
+#include <linux/proc_fs.h>
+#include <linux/slab.h>
+#include <asm/fixmap.h>
+#include <asm/page.h>
+#include <asm/pgalloc.h>
+#include <asm/addrspace.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+#include <asm/mmu.h>
+#include <asm/mmu_context.h>
+
+struct ioremap_map {
+	void __iomem *addr;
+	unsigned long size;
+	unsigned long fixmap_addr;
+};
+
+static struct ioremap_map ioremap_maps[FIX_N_IOREMAPS];
+
+void __init ioremap_fixed_init(void)
+{
+	struct ioremap_map *map;
+	int i;
+
+	for (i = 0; i < FIX_N_IOREMAPS; i++) {
+		map = &ioremap_maps[i];
+		map->fixmap_addr = __fix_to_virt(FIX_IOREMAP_BEGIN + i);
+	}
+}
+
+void __init __iomem *
+ioremap_fixed(resource_size_t phys_addr, unsigned long offset,
+	      unsigned long size, pgprot_t prot)
+{
+	enum fixed_addresses idx0, idx;
+	struct ioremap_map *map;
+	unsigned int nrpages;
+	int i, slot;
+
+	slot = -1;
+	for (i = 0; i < FIX_N_IOREMAPS; i++) {
+		map = &ioremap_maps[i];
+		if (!map->addr) {
+			map->size = size;
+			slot = i;
+			break;
+		}
+	}
+
+	if (slot < 0)
+		return NULL;
+
+	/*
+	 * Mappings have to fit in the FIX_IOREMAP area.
+	 */
+	nrpages = size >> PAGE_SHIFT;
+	if (nrpages > FIX_N_IOREMAPS)
+		return NULL;
+
+	/*
+	 * Ok, go for it..
+	 */
+	idx0 = FIX_IOREMAP_BEGIN + slot;
+	idx = idx0;
+	while (nrpages > 0) {
+		pgprot_val(prot) |= _PAGE_WIRED;
+		__set_fixmap(idx, phys_addr, prot);
+		phys_addr += PAGE_SIZE;
+		idx++;
+		--nrpages;
+	}
+
+	map->addr = (void __iomem *)(offset + map->fixmap_addr);
+	return map->addr;
+}
+
+int iounmap_fixed(void __iomem *addr)
+{
+	enum fixed_addresses idx;
+	struct ioremap_map *map;
+	unsigned int nrpages;
+	int i, slot;
+
+	slot = -1;
+	for (i = 0; i < FIX_N_IOREMAPS; i++) {
+		map = &ioremap_maps[i];
+		if (map->addr == addr) {
+			slot = i;
+			break;
+		}
+	}
+
+	/*
+	 * If we don't match, it's not for us.
+	 */
+	if (slot < 0)
+		return -EINVAL;
+
+	nrpages = map->size >> PAGE_SHIFT;
+
+	idx = FIX_IOREMAP_BEGIN + slot + nrpages - 1;
+	while (nrpages > 0) {
+		__clear_fixmap(idx, __pgprot(_PAGE_WIRED));
+		--idx;
+		--nrpages;
+	}
+
+	map->size = 0;
+	map->addr = NULL;
+
+	return 0;
+}
diff --git a/arch/sh/mm/nommu.c b/arch/sh/mm/nommu.c
index ac16c05..7694f50 100644
--- a/arch/sh/mm/nommu.c
+++ b/arch/sh/mm/nommu.c
@@ -94,3 +94,7 @@
 void __set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t prot)
 {
 }
+
+void pgtable_cache_init(void)
+{
+}
diff --git a/arch/sh/mm/pgtable.c b/arch/sh/mm/pgtable.c
new file mode 100644
index 0000000..6f21fb1
--- /dev/null
+++ b/arch/sh/mm/pgtable.c
@@ -0,0 +1,56 @@
+#include <linux/mm.h>
+
+#define PGALLOC_GFP GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO
+
+static struct kmem_cache *pgd_cachep;
+#if PAGETABLE_LEVELS > 2
+static struct kmem_cache *pmd_cachep;
+#endif
+
+void pgd_ctor(void *x)
+{
+	pgd_t *pgd = x;
+
+	memcpy(pgd + USER_PTRS_PER_PGD,
+	       swapper_pg_dir + USER_PTRS_PER_PGD,
+	       (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
+}
+
+void pgtable_cache_init(void)
+{
+	pgd_cachep = kmem_cache_create("pgd_cache",
+				       PTRS_PER_PGD * (1<<PTE_MAGNITUDE),
+				       PAGE_SIZE, SLAB_PANIC, pgd_ctor);
+#if PAGETABLE_LEVELS > 2
+	pmd_cachep = kmem_cache_create("pmd_cache",
+				       PTRS_PER_PMD * (1<<PTE_MAGNITUDE),
+				       PAGE_SIZE, SLAB_PANIC, NULL);
+#endif
+}
+
+pgd_t *pgd_alloc(struct mm_struct *mm)
+{
+	return kmem_cache_alloc(pgd_cachep, PGALLOC_GFP);
+}
+
+void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+{
+	kmem_cache_free(pgd_cachep, pgd);
+}
+
+#if PAGETABLE_LEVELS > 2
+void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
+{
+	set_pud(pud, __pud((unsigned long)pmd));
+}
+
+pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
+{
+	return kmem_cache_alloc(pmd_cachep, PGALLOC_GFP);
+}
+
+void pmd_free(struct mm_struct *mm, pmd_t *pmd)
+{
+	kmem_cache_free(pmd_cachep, pmd);
+}
+#endif /* PAGETABLE_LEVELS > 2 */
diff --git a/arch/sh/mm/pmb.c b/arch/sh/mm/pmb.c
index 280f6a1..198bcff 100644
--- a/arch/sh/mm/pmb.c
+++ b/arch/sh/mm/pmb.c
@@ -3,11 +3,8 @@
  *
  * Privileged Space Mapping Buffer (PMB) Support.
  *
- * Copyright (C) 2005, 2006, 2007 Paul Mundt
- *
- * P1/P2 Section mapping definitions from map32.h, which was:
- *
- *	Copyright 2003 (c) Lineo Solutions,Inc.
+ * Copyright (C) 2005 - 2010  Paul Mundt
+ * Copyright (C) 2010  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
@@ -24,47 +21,67 @@
 #include <linux/fs.h>
 #include <linux/seq_file.h>
 #include <linux/err.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include <linux/rwlock.h>
+#include <asm/sizes.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
+#include <asm/page.h>
 #include <asm/mmu.h>
-#include <asm/io.h>
 #include <asm/mmu_context.h>
 
-#define NR_PMB_ENTRIES	16
+struct pmb_entry;
 
-static void __pmb_unmap(struct pmb_entry *);
+struct pmb_entry {
+	unsigned long vpn;
+	unsigned long ppn;
+	unsigned long flags;
+	unsigned long size;
 
+	spinlock_t lock;
+
+	/*
+	 * 0 .. NR_PMB_ENTRIES for specific entry selection, or
+	 * PMB_NO_ENTRY to search for a free one
+	 */
+	int entry;
+
+	/* Adjacent entry link for contiguous multi-entry mappings */
+	struct pmb_entry *link;
+};
+
+static void pmb_unmap_entry(struct pmb_entry *, int depth);
+
+static DEFINE_RWLOCK(pmb_rwlock);
 static struct pmb_entry pmb_entry_list[NR_PMB_ENTRIES];
-static unsigned long pmb_map;
+static DECLARE_BITMAP(pmb_map, NR_PMB_ENTRIES);
 
-static inline unsigned long mk_pmb_entry(unsigned int entry)
+static __always_inline unsigned long mk_pmb_entry(unsigned int entry)
 {
 	return (entry & PMB_E_MASK) << PMB_E_SHIFT;
 }
 
-static inline unsigned long mk_pmb_addr(unsigned int entry)
+static __always_inline unsigned long mk_pmb_addr(unsigned int entry)
 {
 	return mk_pmb_entry(entry) | PMB_ADDR;
 }
 
-static inline unsigned long mk_pmb_data(unsigned int entry)
+static __always_inline unsigned long mk_pmb_data(unsigned int entry)
 {
 	return mk_pmb_entry(entry) | PMB_DATA;
 }
 
 static int pmb_alloc_entry(void)
 {
-	unsigned int pos;
+	int pos;
 
-repeat:
-	pos = find_first_zero_bit(&pmb_map, NR_PMB_ENTRIES);
-
-	if (unlikely(pos > NR_PMB_ENTRIES))
-		return -ENOSPC;
-
-	if (test_and_set_bit(pos, &pmb_map))
-		goto repeat;
+	pos = find_first_zero_bit(pmb_map, NR_PMB_ENTRIES);
+	if (pos >= 0 && pos < NR_PMB_ENTRIES)
+		__set_bit(pos, pmb_map);
+	else
+		pos = -ENOSPC;
 
 	return pos;
 }
@@ -73,21 +90,34 @@
 				   unsigned long flags, int entry)
 {
 	struct pmb_entry *pmbe;
+	unsigned long irqflags;
+	void *ret = NULL;
 	int pos;
 
+	write_lock_irqsave(&pmb_rwlock, irqflags);
+
 	if (entry == PMB_NO_ENTRY) {
 		pos = pmb_alloc_entry();
-		if (pos < 0)
-			return ERR_PTR(pos);
+		if (unlikely(pos < 0)) {
+			ret = ERR_PTR(pos);
+			goto out;
+		}
 	} else {
-		if (test_bit(entry, &pmb_map))
-			return ERR_PTR(-ENOSPC);
+		if (__test_and_set_bit(entry, pmb_map)) {
+			ret = ERR_PTR(-ENOSPC);
+			goto out;
+		}
+
 		pos = entry;
 	}
 
+	write_unlock_irqrestore(&pmb_rwlock, irqflags);
+
 	pmbe = &pmb_entry_list[pos];
-	if (!pmbe)
-		return ERR_PTR(-ENOMEM);
+
+	memset(pmbe, 0, sizeof(struct pmb_entry));
+
+	spin_lock_init(&pmbe->lock);
 
 	pmbe->vpn	= vpn;
 	pmbe->ppn	= ppn;
@@ -95,101 +125,113 @@
 	pmbe->entry	= pos;
 
 	return pmbe;
+
+out:
+	write_unlock_irqrestore(&pmb_rwlock, irqflags);
+	return ret;
 }
 
 static void pmb_free(struct pmb_entry *pmbe)
 {
-	int pos = pmbe->entry;
+	__clear_bit(pmbe->entry, pmb_map);
 
-	pmbe->vpn	= 0;
-	pmbe->ppn	= 0;
-	pmbe->flags	= 0;
-	pmbe->entry	= 0;
-
-	clear_bit(pos, &pmb_map);
+	pmbe->entry	= PMB_NO_ENTRY;
+	pmbe->link	= NULL;
 }
 
 /*
- * Must be in P2 for __set_pmb_entry()
+ * Ensure that the PMB entries match our cache configuration.
+ *
+ * When we are in 32-bit address extended mode, CCR.CB becomes
+ * invalid, so care must be taken to manually adjust cacheable
+ * translations.
  */
-static void __set_pmb_entry(unsigned long vpn, unsigned long ppn,
-			    unsigned long flags, int pos)
+static __always_inline unsigned long pmb_cache_flags(void)
 {
-	ctrl_outl(vpn | PMB_V, mk_pmb_addr(pos));
+	unsigned long flags = 0;
 
-#ifdef CONFIG_CACHE_WRITETHROUGH
-	/*
-	 * When we are in 32-bit address extended mode, CCR.CB becomes
-	 * invalid, so care must be taken to manually adjust cacheable
-	 * translations.
-	 */
-	if (likely(flags & PMB_C))
-		flags |= PMB_WT;
+#if defined(CONFIG_CACHE_WRITETHROUGH)
+	flags |= PMB_C | PMB_WT | PMB_UB;
+#elif defined(CONFIG_CACHE_WRITEBACK)
+	flags |= PMB_C;
 #endif
 
-	ctrl_outl(ppn | flags | PMB_V, mk_pmb_data(pos));
+	return flags;
 }
 
-static void __uses_jump_to_uncached set_pmb_entry(struct pmb_entry *pmbe)
+/*
+ * Must be run uncached.
+ */
+static void __set_pmb_entry(struct pmb_entry *pmbe)
 {
-	jump_to_uncached();
-	__set_pmb_entry(pmbe->vpn, pmbe->ppn, pmbe->flags, pmbe->entry);
-	back_to_cached();
+	writel_uncached(pmbe->vpn | PMB_V, mk_pmb_addr(pmbe->entry));
+	writel_uncached(pmbe->ppn | pmbe->flags | PMB_V,
+			mk_pmb_data(pmbe->entry));
 }
 
-static void __uses_jump_to_uncached clear_pmb_entry(struct pmb_entry *pmbe)
+static void __clear_pmb_entry(struct pmb_entry *pmbe)
 {
-	unsigned int entry = pmbe->entry;
-	unsigned long addr;
+	unsigned long addr, data;
+	unsigned long addr_val, data_val;
 
-	if (unlikely(entry >= NR_PMB_ENTRIES))
-		return;
+	addr = mk_pmb_addr(pmbe->entry);
+	data = mk_pmb_data(pmbe->entry);
 
-	jump_to_uncached();
+	addr_val = __raw_readl(addr);
+	data_val = __raw_readl(data);
 
 	/* Clear V-bit */
-	addr = mk_pmb_addr(entry);
-	ctrl_outl(ctrl_inl(addr) & ~PMB_V, addr);
-
-	addr = mk_pmb_data(entry);
-	ctrl_outl(ctrl_inl(addr) & ~PMB_V, addr);
-
-	back_to_cached();
+	writel_uncached(addr_val & ~PMB_V, addr);
+	writel_uncached(data_val & ~PMB_V, data);
 }
 
+static void set_pmb_entry(struct pmb_entry *pmbe)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&pmbe->lock, flags);
+	__set_pmb_entry(pmbe);
+	spin_unlock_irqrestore(&pmbe->lock, flags);
+}
 
 static struct {
 	unsigned long size;
 	int flag;
 } pmb_sizes[] = {
-	{ .size	= 0x20000000, .flag = PMB_SZ_512M, },
-	{ .size = 0x08000000, .flag = PMB_SZ_128M, },
-	{ .size = 0x04000000, .flag = PMB_SZ_64M,  },
-	{ .size = 0x01000000, .flag = PMB_SZ_16M,  },
+	{ .size	= SZ_512M, .flag = PMB_SZ_512M, },
+	{ .size = SZ_128M, .flag = PMB_SZ_128M, },
+	{ .size = SZ_64M,  .flag = PMB_SZ_64M,  },
+	{ .size = SZ_16M,  .flag = PMB_SZ_16M,  },
 };
 
 long pmb_remap(unsigned long vaddr, unsigned long phys,
-	       unsigned long size, unsigned long flags)
+	       unsigned long size, pgprot_t prot)
 {
 	struct pmb_entry *pmbp, *pmbe;
 	unsigned long wanted;
 	int pmb_flags, i;
 	long err;
+	u64 flags;
+
+	flags = pgprot_val(prot);
+
+	pmb_flags = PMB_WT | PMB_UB;
 
 	/* Convert typical pgprot value to the PMB equivalent */
 	if (flags & _PAGE_CACHABLE) {
-		if (flags & _PAGE_WT)
-			pmb_flags = PMB_WT;
-		else
-			pmb_flags = PMB_C;
-	} else
-		pmb_flags = PMB_WT | PMB_UB;
+		pmb_flags |= PMB_C;
+
+		if ((flags & _PAGE_WT) == 0)
+			pmb_flags &= ~(PMB_WT | PMB_UB);
+	}
 
 	pmbp = NULL;
 	wanted = size;
 
 again:
 	for (i = 0; i < ARRAY_SIZE(pmb_sizes); i++) {
+		unsigned long flags;
+
 		if (size < pmb_sizes[i].size)
 			continue;
 
@@ -200,18 +242,25 @@
 			goto out;
 		}
 
-		set_pmb_entry(pmbe);
+		spin_lock_irqsave(&pmbe->lock, flags);
+
+		__set_pmb_entry(pmbe);
 
 		phys	+= pmb_sizes[i].size;
 		vaddr	+= pmb_sizes[i].size;
 		size	-= pmb_sizes[i].size;
 
+		pmbe->size = pmb_sizes[i].size;
+
 		/*
 		 * Link adjacent entries that span multiple PMB entries
 		 * for easier tear-down.
 		 */
-		if (likely(pmbp))
+		if (likely(pmbp)) {
+			spin_lock(&pmbp->lock);
 			pmbp->link = pmbe;
+			spin_unlock(&pmbp->lock);
+		}
 
 		pmbp = pmbe;
 
@@ -221,16 +270,17 @@
 		 * pmb_sizes[i].size again.
 		 */
 		i--;
+
+		spin_unlock_irqrestore(&pmbe->lock, flags);
 	}
 
-	if (size >= 0x1000000)
+	if (size >= SZ_16M)
 		goto again;
 
 	return wanted - size;
 
 out:
-	if (pmbp)
-		__pmb_unmap(pmbp);
+	pmb_unmap_entry(pmbp, NR_PMB_ENTRIES);
 
 	return err;
 }
@@ -240,24 +290,52 @@
 	struct pmb_entry *pmbe = NULL;
 	int i;
 
+	read_lock(&pmb_rwlock);
+
 	for (i = 0; i < ARRAY_SIZE(pmb_entry_list); i++) {
-		if (test_bit(i, &pmb_map)) {
+		if (test_bit(i, pmb_map)) {
 			pmbe = &pmb_entry_list[i];
 			if (pmbe->vpn == addr)
 				break;
 		}
 	}
 
-	if (unlikely(!pmbe))
-		return;
+	read_unlock(&pmb_rwlock);
 
-	__pmb_unmap(pmbe);
+	pmb_unmap_entry(pmbe, NR_PMB_ENTRIES);
 }
 
-static void __pmb_unmap(struct pmb_entry *pmbe)
+static bool pmb_can_merge(struct pmb_entry *a, struct pmb_entry *b)
 {
-	BUG_ON(!test_bit(pmbe->entry, &pmb_map));
+	return (b->vpn == (a->vpn + a->size)) &&
+	       (b->ppn == (a->ppn + a->size)) &&
+	       (b->flags == a->flags);
+}
 
+static bool pmb_size_valid(unsigned long size)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(pmb_sizes); i++)
+		if (pmb_sizes[i].size == size)
+			return true;
+
+	return false;
+}
+
+static int pmb_size_to_flags(unsigned long size)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(pmb_sizes); i++)
+		if (pmb_sizes[i].size == size)
+			return pmb_sizes[i].flag;
+
+	return 0;
+}
+
+static void __pmb_unmap_entry(struct pmb_entry *pmbe, int depth)
+{
 	do {
 		struct pmb_entry *pmblink = pmbe;
 
@@ -268,102 +346,312 @@
 		 * this entry in pmb_alloc() (even if we haven't filled
 		 * it yet).
 		 *
-		 * Therefore, calling clear_pmb_entry() is safe as no
+		 * Therefore, calling __clear_pmb_entry() is safe as no
 		 * other mapping can be using that slot.
 		 */
-		clear_pmb_entry(pmbe);
+		__clear_pmb_entry(pmbe);
 
 		pmbe = pmblink->link;
 
 		pmb_free(pmblink);
-	} while (pmbe);
+	} while (pmbe && --depth);
 }
 
-#ifdef CONFIG_PMB
-int __uses_jump_to_uncached pmb_init(void)
+static void pmb_unmap_entry(struct pmb_entry *pmbe, int depth)
 {
-	unsigned int i;
-	long size, ret;
+	unsigned long flags;
 
-	jump_to_uncached();
+	if (unlikely(!pmbe))
+		return;
 
-	/*
-	 * Insert PMB entries for the P1 and P2 areas so that, after
-	 * we've switched the MMU to 32-bit mode, the semantics of P1
-	 * and P2 are the same as in 29-bit mode, e.g.
-	 *
-	 *	P1 - provides a cached window onto physical memory
-	 *	P2 - provides an uncached window onto physical memory
-	 */
-	size = __MEMORY_START + __MEMORY_SIZE;
-
-	ret = pmb_remap(P1SEG, 0x00000000, size, PMB_C);
-	BUG_ON(ret != size);
-
-	ret = pmb_remap(P2SEG, 0x00000000, size, PMB_WT | PMB_UB);
-	BUG_ON(ret != size);
-
-	ctrl_outl(0, PMB_IRMCR);
-
-	/* PMB.SE and UB[7] */
-	ctrl_outl(PASCR_SE | (1 << 7), PMB_PASCR);
-
-	/* Flush out the TLB */
-	i =  ctrl_inl(MMUCR);
-	i |= MMUCR_TI;
-	ctrl_outl(i, MMUCR);
-
-	back_to_cached();
-
-	return 0;
+	write_lock_irqsave(&pmb_rwlock, flags);
+	__pmb_unmap_entry(pmbe, depth);
+	write_unlock_irqrestore(&pmb_rwlock, flags);
 }
-#else
-int __uses_jump_to_uncached pmb_init(void)
+
+static __always_inline unsigned int pmb_ppn_in_range(unsigned long ppn)
+{
+	return ppn >= __pa(memory_start) && ppn < __pa(memory_end);
+}
+
+static void __init pmb_notify(void)
 {
 	int i;
-	unsigned long addr, data;
 
-	jump_to_uncached();
+	pr_info("PMB: boot mappings:\n");
 
-	for (i = 0; i < PMB_ENTRY_MAX; i++) {
+	read_lock(&pmb_rwlock);
+
+	for (i = 0; i < ARRAY_SIZE(pmb_entry_list); i++) {
 		struct pmb_entry *pmbe;
-		unsigned long vpn, ppn, flags;
 
-		addr = PMB_DATA + (i << PMB_E_SHIFT);
-		data = ctrl_inl(addr);
-		if (!(data & PMB_V))
+		if (!test_bit(i, pmb_map))
 			continue;
 
-		if (data & PMB_C) {
-#if defined(CONFIG_CACHE_WRITETHROUGH)
-			data |= PMB_WT;
-#elif defined(CONFIG_CACHE_WRITEBACK)
-			data &= ~PMB_WT;
-#else
-			data &= ~(PMB_C | PMB_WT);
-#endif
-		}
-		ctrl_outl(data, addr);
+		pmbe = &pmb_entry_list[i];
 
-		ppn = data & PMB_PFN_MASK;
-
-		flags = data & (PMB_C | PMB_WT | PMB_UB);
-		flags |= data & PMB_SZ_MASK;
-
-		addr = PMB_ADDR + (i << PMB_E_SHIFT);
-		data = ctrl_inl(addr);
-
-		vpn = data & PMB_PFN_MASK;
-
-		pmbe = pmb_alloc(vpn, ppn, flags, i);
-		WARN_ON(IS_ERR(pmbe));
+		pr_info("       0x%08lx -> 0x%08lx [ %4ldMB %2scached ]\n",
+			pmbe->vpn >> PAGE_SHIFT, pmbe->ppn >> PAGE_SHIFT,
+			pmbe->size >> 20, (pmbe->flags & PMB_C) ? "" : "un");
 	}
 
-	back_to_cached();
-
-	return 0;
+	read_unlock(&pmb_rwlock);
 }
-#endif /* CONFIG_PMB */
+
+/*
+ * Sync our software copy of the PMB mappings with those in hardware. The
+ * mappings in the hardware PMB were either set up by the bootloader or
+ * very early on by the kernel.
+ */
+static void __init pmb_synchronize(void)
+{
+	struct pmb_entry *pmbp = NULL;
+	int i, j;
+
+	/*
+	 * Run through the initial boot mappings, log the established
+	 * ones, and blow away anything that falls outside of the valid
+	 * PPN range. Specifically, we only care about existing mappings
+	 * that impact the cached/uncached sections.
+	 *
+	 * Note that touching these can be a bit of a minefield; the boot
+	 * loader can establish multi-page mappings with the same caching
+	 * attributes, so we need to ensure that we aren't modifying a
+	 * mapping that we're presently executing from, or may execute
+	 * from in the case of straddling page boundaries.
+	 *
+	 * In the future we will have to tidy up after the boot loader by
+	 * jumping between the cached and uncached mappings and tearing
+	 * down alternating mappings while executing from the other.
+	 */
+	for (i = 0; i < NR_PMB_ENTRIES; i++) {
+		unsigned long addr, data;
+		unsigned long addr_val, data_val;
+		unsigned long ppn, vpn, flags;
+		unsigned long irqflags;
+		unsigned int size;
+		struct pmb_entry *pmbe;
+
+		addr = mk_pmb_addr(i);
+		data = mk_pmb_data(i);
+
+		addr_val = __raw_readl(addr);
+		data_val = __raw_readl(data);
+
+		/*
+		 * Skip over any bogus entries
+		 */
+		if (!(data_val & PMB_V) || !(addr_val & PMB_V))
+			continue;
+
+		ppn = data_val & PMB_PFN_MASK;
+		vpn = addr_val & PMB_PFN_MASK;
+
+		/*
+		 * Only preserve in-range mappings.
+		 */
+		if (!pmb_ppn_in_range(ppn)) {
+			/*
+			 * Invalidate anything out of bounds.
+			 */
+			writel_uncached(addr_val & ~PMB_V, addr);
+			writel_uncached(data_val & ~PMB_V, data);
+			continue;
+		}
+
+		/*
+		 * Update the caching attributes if necessary
+		 */
+		if (data_val & PMB_C) {
+			data_val &= ~PMB_CACHE_MASK;
+			data_val |= pmb_cache_flags();
+
+			writel_uncached(data_val, data);
+		}
+
+		size = data_val & PMB_SZ_MASK;
+		flags = size | (data_val & PMB_CACHE_MASK);
+
+		pmbe = pmb_alloc(vpn, ppn, flags, i);
+		if (IS_ERR(pmbe)) {
+			WARN_ON_ONCE(1);
+			continue;
+		}
+
+		spin_lock_irqsave(&pmbe->lock, irqflags);
+
+		for (j = 0; j < ARRAY_SIZE(pmb_sizes); j++)
+			if (pmb_sizes[j].flag == size)
+				pmbe->size = pmb_sizes[j].size;
+
+		if (pmbp) {
+			spin_lock(&pmbp->lock);
+
+			/*
+			 * Compare the previous entry against the current one to
+			 * see if the entries span a contiguous mapping. If so,
+			 * setup the entry links accordingly. Compound mappings
+			 * are later coalesced.
+			 */
+			if (pmb_can_merge(pmbp, pmbe))
+				pmbp->link = pmbe;
+
+			spin_unlock(&pmbp->lock);
+		}
+
+		pmbp = pmbe;
+
+		spin_unlock_irqrestore(&pmbe->lock, irqflags);
+	}
+}
+
+static void __init pmb_merge(struct pmb_entry *head)
+{
+	unsigned long span, newsize;
+	struct pmb_entry *tail;
+	int i = 1, depth = 0;
+
+	span = newsize = head->size;
+
+	tail = head->link;
+	while (tail) {
+		span += tail->size;
+
+		if (pmb_size_valid(span)) {
+			newsize = span;
+			depth = i;
+		}
+
+		/* This is the end of the line.. */
+		if (!tail->link)
+			break;
+
+		tail = tail->link;
+		i++;
+	}
+
+	/*
+	 * The merged page size must be valid.
+	 */
+	if (!pmb_size_valid(newsize))
+		return;
+
+	head->flags &= ~PMB_SZ_MASK;
+	head->flags |= pmb_size_to_flags(newsize);
+
+	head->size = newsize;
+
+	__pmb_unmap_entry(head->link, depth);
+	__set_pmb_entry(head);
+}
+
+static void __init pmb_coalesce(void)
+{
+	unsigned long flags;
+	int i;
+
+	write_lock_irqsave(&pmb_rwlock, flags);
+
+	for (i = 0; i < ARRAY_SIZE(pmb_entry_list); i++) {
+		struct pmb_entry *pmbe;
+
+		if (!test_bit(i, pmb_map))
+			continue;
+
+		pmbe = &pmb_entry_list[i];
+
+		/*
+		 * We're only interested in compound mappings
+		 */
+		if (!pmbe->link)
+			continue;
+
+		/*
+		 * Nothing to do if it already uses the largest possible
+		 * page size.
+		 */
+		if (pmbe->size == SZ_512M)
+			continue;
+
+		pmb_merge(pmbe);
+	}
+
+	write_unlock_irqrestore(&pmb_rwlock, flags);
+}
+
+#ifdef CONFIG_UNCACHED_MAPPING
+static void __init pmb_resize(void)
+{
+	int i;
+
+	/*
+	 * If the uncached mapping was constructed by the kernel, it will
+	 * already be a reasonable size.
+	 */
+	if (uncached_size == SZ_16M)
+		return;
+
+	read_lock(&pmb_rwlock);
+
+	for (i = 0; i < ARRAY_SIZE(pmb_entry_list); i++) {
+		struct pmb_entry *pmbe;
+		unsigned long flags;
+
+		if (!test_bit(i, pmb_map))
+			continue;
+
+		pmbe = &pmb_entry_list[i];
+
+		if (pmbe->vpn != uncached_start)
+			continue;
+
+		/*
+		 * Found it, now resize it.
+		 */
+		spin_lock_irqsave(&pmbe->lock, flags);
+
+		pmbe->size = SZ_16M;
+		pmbe->flags &= ~PMB_SZ_MASK;
+		pmbe->flags |= pmb_size_to_flags(pmbe->size);
+
+		uncached_resize(pmbe->size);
+
+		__set_pmb_entry(pmbe);
+
+		spin_unlock_irqrestore(&pmbe->lock, flags);
+	}
+
+	read_lock(&pmb_rwlock);
+}
+#endif
+
+void __init pmb_init(void)
+{
+	/* Synchronize software state */
+	pmb_synchronize();
+
+	/* Attempt to combine compound mappings */
+	pmb_coalesce();
+
+#ifdef CONFIG_UNCACHED_MAPPING
+	/* Resize initial mappings, if necessary */
+	pmb_resize();
+#endif
+
+	/* Log them */
+	pmb_notify();
+
+	writel_uncached(0, PMB_IRMCR);
+
+	/* Flush out the TLB */
+	__raw_writel(__raw_readl(MMUCR) | MMUCR_TI, MMUCR);
+	ctrl_barrier();
+}
+
+bool __in_29bit_mode(void)
+{
+        return (__raw_readl(PMB_PASCR) & PASCR_SE) == 0;
+}
 
 static int pmb_seq_show(struct seq_file *file, void *iter)
 {
@@ -378,8 +666,8 @@
 		unsigned int size;
 		char *sz_str = NULL;
 
-		addr = ctrl_inl(mk_pmb_addr(i));
-		data = ctrl_inl(mk_pmb_data(i));
+		addr = __raw_readl(mk_pmb_addr(i));
+		data = __raw_readl(mk_pmb_data(i));
 
 		size = data & PMB_SZ_MASK;
 		sz_str = (size == PMB_SZ_16M)  ? " 16MB":
@@ -437,14 +725,21 @@
 	if (state.event == PM_EVENT_ON &&
 	    prev_state.event == PM_EVENT_FREEZE) {
 		struct pmb_entry *pmbe;
+
+		read_lock(&pmb_rwlock);
+
 		for (i = 0; i < ARRAY_SIZE(pmb_entry_list); i++) {
-			if (test_bit(i, &pmb_map)) {
+			if (test_bit(i, pmb_map)) {
 				pmbe = &pmb_entry_list[i];
 				set_pmb_entry(pmbe);
 			}
 		}
+
+		read_unlock(&pmb_rwlock);
 	}
+
 	prev_state = state;
+
 	return 0;
 }
 
@@ -462,6 +757,5 @@
 {
 	return sysdev_driver_register(&cpu_sysdev_class, &pmb_sysdev_driver);
 }
-
 subsys_initcall(pmb_sysdev_init);
 #endif
diff --git a/arch/sh/mm/tlb-pteaex.c b/arch/sh/mm/tlb-pteaex.c
index 409b7c2..32dc674 100644
--- a/arch/sh/mm/tlb-pteaex.c
+++ b/arch/sh/mm/tlb-pteaex.c
@@ -68,8 +68,7 @@
  * in extended mode, the legacy 8-bit ASID field in address array 1 has
  * undefined behaviour.
  */
-void __uses_jump_to_uncached local_flush_tlb_one(unsigned long asid,
-						 unsigned long page)
+void local_flush_tlb_one(unsigned long asid, unsigned long page)
 {
 	jump_to_uncached();
 	__raw_writel(page, MMU_UTLB_ADDRESS_ARRAY | MMU_PAGE_ASSOC_BIT);
diff --git a/arch/sh/mm/tlb-sh3.c b/arch/sh/mm/tlb-sh3.c
index ace8e6d..4f5f7cb 100644
--- a/arch/sh/mm/tlb-sh3.c
+++ b/arch/sh/mm/tlb-sh3.c
@@ -41,14 +41,14 @@
 
 	/* Set PTEH register */
 	vpn = (address & MMU_VPN_MASK) | get_asid();
-	ctrl_outl(vpn, MMU_PTEH);
+	__raw_writel(vpn, MMU_PTEH);
 
 	pteval = pte_val(pte);
 
 	/* Set PTEL register */
 	pteval &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */
 	/* conveniently, we want all the software flags to be 0 anyway */
-	ctrl_outl(pteval, MMU_PTEL);
+	__raw_writel(pteval, MMU_PTEL);
 
 	/* Load the TLB */
 	asm volatile("ldtlb": /* no output */ : /* no input */ : "memory");
@@ -75,5 +75,5 @@
 	}
 
 	for (i = 0; i < ways; i++)
-		ctrl_outl(data, addr + (i << 8));
+		__raw_writel(data, addr + (i << 8));
 }
diff --git a/arch/sh/mm/tlb-sh4.c b/arch/sh/mm/tlb-sh4.c
index 8cf550e..ccac77f 100644
--- a/arch/sh/mm/tlb-sh4.c
+++ b/arch/sh/mm/tlb-sh4.c
@@ -29,7 +29,7 @@
 
 	/* Set PTEH register */
 	vpn = (address & MMU_VPN_MASK) | get_asid();
-	ctrl_outl(vpn, MMU_PTEH);
+	__raw_writel(vpn, MMU_PTEH);
 
 	pteval = pte.pte_low;
 
@@ -41,13 +41,13 @@
 	 * the protection bits (with the exception of the compat-mode SZ
 	 * and PR bits, which are cleared) being written out in PTEL.
 	 */
-	ctrl_outl(pte.pte_high, MMU_PTEA);
+	__raw_writel(pte.pte_high, MMU_PTEA);
 #else
 	if (cpu_data->flags & CPU_HAS_PTEA) {
 		/* The last 3 bits and the first one of pteval contains
 		 * the PTEA timing control and space attribute bits
 		 */
-		ctrl_outl(copy_ptea_attributes(pteval), MMU_PTEA);
+		__raw_writel(copy_ptea_attributes(pteval), MMU_PTEA);
 	}
 #endif
 
@@ -57,15 +57,14 @@
 	pteval |= _PAGE_WT;
 #endif
 	/* conveniently, we want all the software flags to be 0 anyway */
-	ctrl_outl(pteval, MMU_PTEL);
+	__raw_writel(pteval, MMU_PTEL);
 
 	/* Load the TLB */
 	asm volatile("ldtlb": /* no output */ : /* no input */ : "memory");
 	local_irq_restore(flags);
 }
 
-void __uses_jump_to_uncached local_flush_tlb_one(unsigned long asid,
-						 unsigned long page)
+void local_flush_tlb_one(unsigned long asid, unsigned long page)
 {
 	unsigned long addr, data;
 
@@ -78,6 +77,6 @@
 	addr = MMU_UTLB_ADDRESS_ARRAY | MMU_PAGE_ASSOC_BIT;
 	data = page | asid; /* VALID bit is off */
 	jump_to_uncached();
-	ctrl_outl(data, addr);
+	__raw_writel(data, addr);
 	back_to_cached();
 }
diff --git a/arch/sh/mm/tlb-sh5.c b/arch/sh/mm/tlb-sh5.c
index fdb64e4..f27dbe1 100644
--- a/arch/sh/mm/tlb-sh5.c
+++ b/arch/sh/mm/tlb-sh5.c
@@ -143,3 +143,42 @@
  */
 void sh64_teardown_tlb_slot(unsigned long long config_addr)
 	__attribute__ ((alias("__flush_tlb_slot")));
+
+static int dtlb_entry;
+static unsigned long long dtlb_entries[64];
+
+void tlb_wire_entry(struct vm_area_struct *vma, unsigned long addr, pte_t pte)
+{
+	unsigned long long entry;
+	unsigned long paddr, flags;
+
+	BUG_ON(dtlb_entry == ARRAY_SIZE(dtlb_entries));
+
+	local_irq_save(flags);
+
+	entry = sh64_get_wired_dtlb_entry();
+	dtlb_entries[dtlb_entry++] = entry;
+
+	paddr = pte_val(pte) & _PAGE_FLAGS_HARDWARE_MASK;
+	paddr &= ~PAGE_MASK;
+
+	sh64_setup_tlb_slot(entry, addr, get_asid(), paddr);
+
+	local_irq_restore(flags);
+}
+
+void tlb_unwire_entry(void)
+{
+	unsigned long long entry;
+	unsigned long flags;
+
+	BUG_ON(!dtlb_entry);
+
+	local_irq_save(flags);
+	entry = dtlb_entries[dtlb_entry--];
+
+	sh64_teardown_tlb_slot(entry);
+	sh64_put_wired_dtlb_entry(entry);
+
+	local_irq_restore(flags);
+}
diff --git a/arch/sh/mm/tlb-urb.c b/arch/sh/mm/tlb-urb.c
new file mode 100644
index 0000000..bb5b909
--- /dev/null
+++ b/arch/sh/mm/tlb-urb.c
@@ -0,0 +1,81 @@
+/*
+ * arch/sh/mm/tlb-urb.c
+ *
+ * TLB entry wiring helpers for URB-equipped parts.
+ *
+ * Copyright (C) 2010  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 <linux/mm.h>
+#include <linux/io.h>
+#include <asm/tlb.h>
+#include <asm/mmu_context.h>
+
+/*
+ * Load the entry for 'addr' into the TLB and wire the entry.
+ */
+void tlb_wire_entry(struct vm_area_struct *vma, unsigned long addr, pte_t pte)
+{
+	unsigned long status, flags;
+	int urb;
+
+	local_irq_save(flags);
+
+	/* Load the entry into the TLB */
+	__update_tlb(vma, addr, pte);
+
+	/* ... and wire it up. */
+	status = __raw_readl(MMUCR);
+	urb = (status & MMUCR_URB) >> MMUCR_URB_SHIFT;
+	status &= ~MMUCR_URB;
+
+	/*
+	 * Make sure we're not trying to wire the last TLB entry slot.
+	 */
+	BUG_ON(!--urb);
+
+	urb = urb % MMUCR_URB_NENTRIES;
+
+	status |= (urb << MMUCR_URB_SHIFT);
+	__raw_writel(status, MMUCR);
+	ctrl_barrier();
+
+	local_irq_restore(flags);
+}
+
+/*
+ * Unwire the last wired TLB entry.
+ *
+ * It should also be noted that it is not possible to wire and unwire
+ * TLB entries in an arbitrary order. If you wire TLB entry N, followed
+ * by entry N+1, you must unwire entry N+1 first, then entry N. In this
+ * respect, it works like a stack or LIFO queue.
+ */
+void tlb_unwire_entry(void)
+{
+	unsigned long status, flags;
+	int urb;
+
+	local_irq_save(flags);
+
+	status = __raw_readl(MMUCR);
+	urb = (status & MMUCR_URB) >> MMUCR_URB_SHIFT;
+	status &= ~MMUCR_URB;
+
+	/*
+	 * Make sure we're not trying to unwire a TLB entry when none
+	 * have been wired.
+	 */
+	BUG_ON(urb++ == MMUCR_URB_NENTRIES);
+
+	urb = urb % MMUCR_URB_NENTRIES;
+
+	status |= (urb << MMUCR_URB_SHIFT);
+	__raw_writel(status, MMUCR);
+	ctrl_barrier();
+
+	local_irq_restore(flags);
+}
diff --git a/arch/sh/mm/tlbflush_32.c b/arch/sh/mm/tlbflush_32.c
index 6f45c1f..004bb3f2 100644
--- a/arch/sh/mm/tlbflush_32.c
+++ b/arch/sh/mm/tlbflush_32.c
@@ -132,9 +132,9 @@
 	 *      It's same position, bit #2.
 	 */
 	local_irq_save(flags);
-	status = ctrl_inl(MMUCR);
+	status = __raw_readl(MMUCR);
 	status |= 0x04;
-	ctrl_outl(status, MMUCR);
+	__raw_writel(status, MMUCR);
 	ctrl_barrier();
 	local_irq_restore(flags);
 }
diff --git a/arch/sh/mm/tlbflush_64.c b/arch/sh/mm/tlbflush_64.c
index de0b0e88..706da1d 100644
--- a/arch/sh/mm/tlbflush_64.c
+++ b/arch/sh/mm/tlbflush_64.c
@@ -36,7 +36,7 @@
 
 static inline void print_prots(pgprot_t prot)
 {
-	printk("prot is 0x%08lx\n",pgprot_val(prot));
+	printk("prot is 0x%016llx\n",pgprot_val(prot));
 
 	printk("%s %s %s %s %s\n",PPROT(_PAGE_SHARED),PPROT(_PAGE_READ),
 	       PPROT(_PAGE_EXECUTE),PPROT(_PAGE_WRITE),PPROT(_PAGE_USER));
diff --git a/arch/sh/mm/uncached.c b/arch/sh/mm/uncached.c
new file mode 100644
index 0000000..cf20a5c
--- /dev/null
+++ b/arch/sh/mm/uncached.c
@@ -0,0 +1,34 @@
+#include <linux/init.h>
+#include <asm/sizes.h>
+#include <asm/page.h>
+
+/*
+ * This is the offset of the uncached section from its cached alias.
+ *
+ * Legacy platforms handle trivial transitions between cached and
+ * uncached segments by making use of the 1:1 mapping relationship in
+ * 512MB lowmem, others via a special uncached mapping.
+ *
+ * Default value only valid in 29 bit mode, in 32bit mode this will be
+ * updated by the early PMB initialization code.
+ */
+unsigned long cached_to_uncached = SZ_512M;
+unsigned long uncached_size = SZ_512M;
+unsigned long uncached_start, uncached_end;
+
+int virt_addr_uncached(unsigned long kaddr)
+{
+	return (kaddr >= uncached_start) && (kaddr < uncached_end);
+}
+
+void __init uncached_init(void)
+{
+	uncached_start = memory_end;
+	uncached_end = uncached_start + uncached_size;
+}
+
+void __init uncached_resize(unsigned long size)
+{
+	uncached_size = size;
+	uncached_end = uncached_start + uncached_size;
+}
diff --git a/arch/sh/tools/mach-types b/arch/sh/tools/mach-types
index 6639b25..b25aa55 100644
--- a/arch/sh/tools/mach-types
+++ b/arch/sh/tools/mach-types
@@ -32,6 +32,7 @@
 SNAPGEAR		SH_SECUREEDGE5410
 EDOSK7705		SH_EDOSK7705
 EDOSK7760		SH_EDOSK7760
+SDK7786			SH_SDK7786
 SH4202_MICRODEV		SH_SH4202_MICRODEV
 SH03			SH_SH03
 LANDISK			SH_LANDISK
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index 6b3e0c2..6fe4f77 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -603,18 +603,13 @@
 	p->irqaction.handler = sh_cmt_interrupt;
 	p->irqaction.dev_id = p;
 	p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL;
-	ret = setup_irq(irq, &p->irqaction);
-	if (ret) {
-		pr_err("sh_cmt: failed to request irq %d\n", irq);
-		goto err1;
-	}
 
 	/* get hold of clock */
 	p->clk = clk_get(&p->pdev->dev, cfg->clk);
 	if (IS_ERR(p->clk)) {
 		pr_err("sh_cmt: cannot get clock \"%s\"\n", cfg->clk);
 		ret = PTR_ERR(p->clk);
-		goto err2;
+		goto err1;
 	}
 
 	if (resource_size(res) == 6) {
@@ -627,14 +622,25 @@
 		p->clear_bits = ~0xc000;
 	}
 
-	return sh_cmt_register(p, cfg->name,
-			       cfg->clockevent_rating,
-			       cfg->clocksource_rating);
- err2:
-	remove_irq(irq, &p->irqaction);
- err1:
+	ret = sh_cmt_register(p, cfg->name,
+			      cfg->clockevent_rating,
+			      cfg->clocksource_rating);
+	if (ret) {
+		pr_err("sh_cmt: registration failed\n");
+		goto err1;
+	}
+
+	ret = setup_irq(irq, &p->irqaction);
+	if (ret) {
+		pr_err("sh_cmt: failed to request irq %d\n", irq);
+		goto err1;
+	}
+
+	return 0;
+
+err1:
 	iounmap(p->mapbase);
- err0:
+err0:
 	return ret;
 }
 
diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c
index 973e714..4c8a759 100644
--- a/drivers/clocksource/sh_mtu2.c
+++ b/drivers/clocksource/sh_mtu2.c
@@ -221,15 +221,15 @@
 	ced->cpumask = cpumask_of(0);
 	ced->set_mode = sh_mtu2_clock_event_mode;
 
+	pr_info("sh_mtu2: %s used for clock events\n", ced->name);
+	clockevents_register_device(ced);
+
 	ret = setup_irq(p->irqaction.irq, &p->irqaction);
 	if (ret) {
 		pr_err("sh_mtu2: failed to request irq %d\n",
 		       p->irqaction.irq);
 		return;
 	}
-
-	pr_info("sh_mtu2: %s used for clock events\n", ced->name);
-	clockevents_register_device(ced);
 }
 
 static int sh_mtu2_register(struct sh_mtu2_priv *p, char *name,
diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c
index 93c2322..961f5b5 100644
--- a/drivers/clocksource/sh_tmu.c
+++ b/drivers/clocksource/sh_tmu.c
@@ -323,15 +323,15 @@
 	ced->set_next_event = sh_tmu_clock_event_next;
 	ced->set_mode = sh_tmu_clock_event_mode;
 
+	pr_info("sh_tmu: %s used for clock events\n", ced->name);
+	clockevents_register_device(ced);
+
 	ret = setup_irq(p->irqaction.irq, &p->irqaction);
 	if (ret) {
 		pr_err("sh_tmu: failed to request irq %d\n",
 		       p->irqaction.irq);
 		return;
 	}
-
-	pr_info("sh_tmu: %s used for clock events\n", ced->name);
-	clockevents_register_device(ced);
 }
 
 static int sh_tmu_register(struct sh_tmu_priv *p, char *name,
diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c
index d10cc89..b75ce8b 100644
--- a/drivers/dma/shdma.c
+++ b/drivers/dma/shdma.c
@@ -48,23 +48,20 @@
  */
 #define RS_DEFAULT  (RS_DUAL)
 
+/* A bitmask with bits enough for enum sh_dmae_slave_chan_id */
+static unsigned long sh_dmae_slave_used[BITS_TO_LONGS(SHDMA_SLAVE_NUMBER)];
+
 static void sh_dmae_chan_ld_cleanup(struct sh_dmae_chan *sh_chan, bool all);
 
 #define SH_DMAC_CHAN_BASE(id) (dma_base_addr[id])
 static void sh_dmae_writel(struct sh_dmae_chan *sh_dc, u32 data, u32 reg)
 {
-	ctrl_outl(data, (SH_DMAC_CHAN_BASE(sh_dc->id) + reg));
+	ctrl_outl(data, SH_DMAC_CHAN_BASE(sh_dc->id) + reg);
 }
 
 static u32 sh_dmae_readl(struct sh_dmae_chan *sh_dc, u32 reg)
 {
-	return ctrl_inl((SH_DMAC_CHAN_BASE(sh_dc->id) + reg));
-}
-
-static void dmae_init(struct sh_dmae_chan *sh_chan)
-{
-	u32 chcr = RS_DEFAULT; /* default is DUAL mode */
-	sh_dmae_writel(sh_chan, chcr, CHCR);
+	return ctrl_inl(SH_DMAC_CHAN_BASE(sh_dc->id) + reg);
 }
 
 /*
@@ -95,27 +92,30 @@
 	return 0;
 }
 
-static int dmae_is_busy(struct sh_dmae_chan *sh_chan)
+static bool dmae_is_busy(struct sh_dmae_chan *sh_chan)
 {
 	u32 chcr = sh_dmae_readl(sh_chan, CHCR);
-	if (chcr & CHCR_DE) {
-		if (!(chcr & CHCR_TE))
-			return -EBUSY; /* working */
-	}
-	return 0; /* waiting */
+
+	if ((chcr & (CHCR_DE | CHCR_TE)) == CHCR_DE)
+		return true; /* working */
+
+	return false; /* waiting */
 }
 
-static inline unsigned int calc_xmit_shift(struct sh_dmae_chan *sh_chan)
+static unsigned int ts_shift[] = TS_SHIFT;
+static inline unsigned int calc_xmit_shift(u32 chcr)
 {
-	u32 chcr = sh_dmae_readl(sh_chan, CHCR);
-	return ts_shift[(chcr & CHCR_TS_MASK) >> CHCR_TS_SHIFT];
+	int cnt = ((chcr & CHCR_TS_LOW_MASK) >> CHCR_TS_LOW_SHIFT) |
+		((chcr & CHCR_TS_HIGH_MASK) >> CHCR_TS_HIGH_SHIFT);
+
+	return ts_shift[cnt];
 }
 
 static void dmae_set_reg(struct sh_dmae_chan *sh_chan, struct sh_dmae_regs *hw)
 {
 	sh_dmae_writel(sh_chan, hw->sar, SAR);
 	sh_dmae_writel(sh_chan, hw->dar, DAR);
-	sh_dmae_writel(sh_chan, hw->tcr >> calc_xmit_shift(sh_chan), TCR);
+	sh_dmae_writel(sh_chan, hw->tcr >> sh_chan->xmit_shift, TCR);
 }
 
 static void dmae_start(struct sh_dmae_chan *sh_chan)
@@ -123,7 +123,7 @@
 	u32 chcr = sh_dmae_readl(sh_chan, CHCR);
 
 	chcr |= CHCR_DE | CHCR_IE;
-	sh_dmae_writel(sh_chan, chcr, CHCR);
+	sh_dmae_writel(sh_chan, chcr & ~CHCR_TE, CHCR);
 }
 
 static void dmae_halt(struct sh_dmae_chan *sh_chan)
@@ -134,55 +134,50 @@
 	sh_dmae_writel(sh_chan, chcr, CHCR);
 }
 
+static void dmae_init(struct sh_dmae_chan *sh_chan)
+{
+	u32 chcr = RS_DEFAULT; /* default is DUAL mode */
+	sh_chan->xmit_shift = calc_xmit_shift(chcr);
+	sh_dmae_writel(sh_chan, chcr, CHCR);
+}
+
 static int dmae_set_chcr(struct sh_dmae_chan *sh_chan, u32 val)
 {
-	int ret = dmae_is_busy(sh_chan);
 	/* When DMA was working, can not set data to CHCR */
-	if (ret)
-		return ret;
+	if (dmae_is_busy(sh_chan))
+		return -EBUSY;
 
+	sh_chan->xmit_shift = calc_xmit_shift(val);
 	sh_dmae_writel(sh_chan, val, CHCR);
+
 	return 0;
 }
 
-#define DMARS1_ADDR	0x04
-#define DMARS2_ADDR	0x08
-#define DMARS_SHIFT 8
-#define DMARS_CHAN_MSK 0x01
+#define DMARS_SHIFT	8
+#define DMARS_CHAN_MSK	0x01
 static int dmae_set_dmars(struct sh_dmae_chan *sh_chan, u16 val)
 {
 	u32 addr;
 	int shift = 0;
-	int ret = dmae_is_busy(sh_chan);
-	if (ret)
-		return ret;
+
+	if (dmae_is_busy(sh_chan))
+		return -EBUSY;
 
 	if (sh_chan->id & DMARS_CHAN_MSK)
 		shift = DMARS_SHIFT;
 
-	switch (sh_chan->id) {
-	/* DMARS0 */
-	case 0:
-	case 1:
-		addr = SH_DMARS_BASE;
-		break;
-	/* DMARS1 */
-	case 2:
-	case 3:
-		addr = (SH_DMARS_BASE + DMARS1_ADDR);
-		break;
-	/* DMARS2 */
-	case 4:
-	case 5:
-		addr = (SH_DMARS_BASE + DMARS2_ADDR);
-		break;
-	default:
+	if (sh_chan->id < 6)
+		/* DMA0RS0 - DMA0RS2 */
+		addr = SH_DMARS_BASE0 + (sh_chan->id / 2) * 4;
+#ifdef SH_DMARS_BASE1
+	else if (sh_chan->id < 12)
+		/* DMA1RS0 - DMA1RS2 */
+		addr = SH_DMARS_BASE1 + ((sh_chan->id - 6) / 2) * 4;
+#endif
+	else
 		return -EINVAL;
-	}
 
-	ctrl_outw((val << shift) |
-		(ctrl_inw(addr) & (shift ? 0xFF00 : 0x00FF)),
-		addr);
+	ctrl_outw((val << shift) | (ctrl_inw(addr) & (0xFF00 >> shift)), addr);
 
 	return 0;
 }
@@ -250,10 +245,53 @@
 	return NULL;
 }
 
+static struct sh_dmae_slave_config *sh_dmae_find_slave(
+	struct sh_dmae_chan *sh_chan, enum sh_dmae_slave_chan_id slave_id)
+{
+	struct dma_device *dma_dev = sh_chan->common.device;
+	struct sh_dmae_device *shdev = container_of(dma_dev,
+					struct sh_dmae_device, common);
+	struct sh_dmae_pdata *pdata = &shdev->pdata;
+	int i;
+
+	if ((unsigned)slave_id >= SHDMA_SLAVE_NUMBER)
+		return NULL;
+
+	for (i = 0; i < pdata->config_num; i++)
+		if (pdata->config[i].slave_id == slave_id)
+			return pdata->config + i;
+
+	return NULL;
+}
+
 static int sh_dmae_alloc_chan_resources(struct dma_chan *chan)
 {
 	struct sh_dmae_chan *sh_chan = to_sh_chan(chan);
 	struct sh_desc *desc;
+	struct sh_dmae_slave *param = chan->private;
+
+	/*
+	 * This relies on the guarantee from dmaengine that alloc_chan_resources
+	 * never runs concurrently with itself or free_chan_resources.
+	 */
+	if (param) {
+		struct sh_dmae_slave_config *cfg;
+
+		cfg = sh_dmae_find_slave(sh_chan, param->slave_id);
+		if (!cfg)
+			return -EINVAL;
+
+		if (test_and_set_bit(param->slave_id, sh_dmae_slave_used))
+			return -EBUSY;
+
+		param->config = cfg;
+
+		dmae_set_dmars(sh_chan, cfg->mid_rid);
+		dmae_set_chcr(sh_chan, cfg->chcr);
+	} else {
+		if ((sh_dmae_readl(sh_chan, CHCR) & 0x700) != 0x400)
+			dmae_set_chcr(sh_chan, RS_DEFAULT);
+	}
 
 	spin_lock_bh(&sh_chan->desc_lock);
 	while (sh_chan->descs_allocated < NR_DESCS_PER_CHANNEL) {
@@ -286,10 +324,18 @@
 	struct sh_desc *desc, *_desc;
 	LIST_HEAD(list);
 
+	dmae_halt(sh_chan);
+
 	/* Prepared and not submitted descriptors can still be on the queue */
 	if (!list_empty(&sh_chan->ld_queue))
 		sh_dmae_chan_ld_cleanup(sh_chan, true);
 
+	if (chan->private) {
+		/* The caller is holding dma_list_mutex */
+		struct sh_dmae_slave *param = chan->private;
+		clear_bit(param->slave_id, sh_dmae_slave_used);
+	}
+
 	spin_lock_bh(&sh_chan->desc_lock);
 
 	list_splice_init(&sh_chan->ld_free, &list);
@@ -301,23 +347,97 @@
 		kfree(desc);
 }
 
-static struct dma_async_tx_descriptor *sh_dmae_prep_memcpy(
-	struct dma_chan *chan, dma_addr_t dma_dest, dma_addr_t dma_src,
-	size_t len, unsigned long flags)
+/**
+ * sh_dmae_add_desc - get, set up and return one transfer descriptor
+ * @sh_chan:	DMA channel
+ * @flags:	DMA transfer flags
+ * @dest:	destination DMA address, incremented when direction equals
+ *		DMA_FROM_DEVICE or DMA_BIDIRECTIONAL
+ * @src:	source DMA address, incremented when direction equals
+ *		DMA_TO_DEVICE or DMA_BIDIRECTIONAL
+ * @len:	DMA transfer length
+ * @first:	if NULL, set to the current descriptor and cookie set to -EBUSY
+ * @direction:	needed for slave DMA to decide which address to keep constant,
+ *		equals DMA_BIDIRECTIONAL for MEMCPY
+ * Returns 0 or an error
+ * Locks: called with desc_lock held
+ */
+static struct sh_desc *sh_dmae_add_desc(struct sh_dmae_chan *sh_chan,
+	unsigned long flags, dma_addr_t *dest, dma_addr_t *src, size_t *len,
+	struct sh_desc **first, enum dma_data_direction direction)
 {
-	struct sh_dmae_chan *sh_chan;
-	struct sh_desc *first = NULL, *prev = NULL, *new;
+	struct sh_desc *new;
 	size_t copy_size;
+
+	if (!*len)
+		return NULL;
+
+	/* Allocate the link descriptor from the free list */
+	new = sh_dmae_get_desc(sh_chan);
+	if (!new) {
+		dev_err(sh_chan->dev, "No free link descriptor available\n");
+		return NULL;
+	}
+
+	copy_size = min(*len, (size_t)SH_DMA_TCR_MAX + 1);
+
+	new->hw.sar = *src;
+	new->hw.dar = *dest;
+	new->hw.tcr = copy_size;
+
+	if (!*first) {
+		/* First desc */
+		new->async_tx.cookie = -EBUSY;
+		*first = new;
+	} else {
+		/* Other desc - invisible to the user */
+		new->async_tx.cookie = -EINVAL;
+	}
+
+	dev_dbg(sh_chan->dev,
+		"chaining (%u/%u)@%x -> %x with %p, cookie %d, shift %d\n",
+		copy_size, *len, *src, *dest, &new->async_tx,
+		new->async_tx.cookie, sh_chan->xmit_shift);
+
+	new->mark = DESC_PREPARED;
+	new->async_tx.flags = flags;
+	new->direction = direction;
+
+	*len -= copy_size;
+	if (direction == DMA_BIDIRECTIONAL || direction == DMA_TO_DEVICE)
+		*src += copy_size;
+	if (direction == DMA_BIDIRECTIONAL || direction == DMA_FROM_DEVICE)
+		*dest += copy_size;
+
+	return new;
+}
+
+/*
+ * sh_dmae_prep_sg - prepare transfer descriptors from an SG list
+ *
+ * Common routine for public (MEMCPY) and slave DMA. The MEMCPY case is also
+ * converted to scatter-gather to guarantee consistent locking and a correct
+ * list manipulation. For slave DMA direction carries the usual meaning, and,
+ * logically, the SG list is RAM and the addr variable contains slave address,
+ * e.g., the FIFO I/O register. For MEMCPY direction equals DMA_BIDIRECTIONAL
+ * and the SG list contains only one element and points at the source buffer.
+ */
+static struct dma_async_tx_descriptor *sh_dmae_prep_sg(struct sh_dmae_chan *sh_chan,
+	struct scatterlist *sgl, unsigned int sg_len, dma_addr_t *addr,
+	enum dma_data_direction direction, unsigned long flags)
+{
+	struct scatterlist *sg;
+	struct sh_desc *first = NULL, *new = NULL /* compiler... */;
 	LIST_HEAD(tx_list);
-	int chunks = (len + SH_DMA_TCR_MAX) / (SH_DMA_TCR_MAX + 1);
+	int chunks = 0;
+	int i;
 
-	if (!chan)
+	if (!sg_len)
 		return NULL;
 
-	if (!len)
-		return NULL;
-
-	sh_chan = to_sh_chan(chan);
+	for_each_sg(sgl, sg, sg_len, i)
+		chunks += (sg_dma_len(sg) + SH_DMA_TCR_MAX) /
+			(SH_DMA_TCR_MAX + 1);
 
 	/* Have to lock the whole loop to protect against concurrent release */
 	spin_lock_bh(&sh_chan->desc_lock);
@@ -333,49 +453,32 @@
 	 *	only during this function, then they are immediately spliced
 	 *	back onto the free list in form of a chain
 	 */
-	do {
-		/* Allocate the link descriptor from the free list */
-		new = sh_dmae_get_desc(sh_chan);
-		if (!new) {
-			dev_err(sh_chan->dev,
-				"No free memory for link descriptor\n");
-			list_for_each_entry(new, &tx_list, node)
-				new->mark = DESC_IDLE;
-			list_splice(&tx_list, &sh_chan->ld_free);
-			spin_unlock_bh(&sh_chan->desc_lock);
-			return NULL;
-		}
+	for_each_sg(sgl, sg, sg_len, i) {
+		dma_addr_t sg_addr = sg_dma_address(sg);
+		size_t len = sg_dma_len(sg);
 
-		copy_size = min(len, (size_t)SH_DMA_TCR_MAX + 1);
+		if (!len)
+			goto err_get_desc;
 
-		new->hw.sar = dma_src;
-		new->hw.dar = dma_dest;
-		new->hw.tcr = copy_size;
-		if (!first) {
-			/* First desc */
-			new->async_tx.cookie = -EBUSY;
-			first = new;
-		} else {
-			/* Other desc - invisible to the user */
-			new->async_tx.cookie = -EINVAL;
-		}
+		do {
+			dev_dbg(sh_chan->dev, "Add SG #%d@%p[%d], dma %llx\n",
+				i, sg, len, (unsigned long long)sg_addr);
 
-		dev_dbg(sh_chan->dev,
-			"chaining %u of %u with %p, dst %x, cookie %d\n",
-			copy_size, len, &new->async_tx, dma_dest,
-			new->async_tx.cookie);
+			if (direction == DMA_FROM_DEVICE)
+				new = sh_dmae_add_desc(sh_chan, flags,
+						&sg_addr, addr, &len, &first,
+						direction);
+			else
+				new = sh_dmae_add_desc(sh_chan, flags,
+						addr, &sg_addr, &len, &first,
+						direction);
+			if (!new)
+				goto err_get_desc;
 
-		new->mark = DESC_PREPARED;
-		new->async_tx.flags = flags;
-		new->chunks = chunks--;
-
-		prev = new;
-		len -= copy_size;
-		dma_src += copy_size;
-		dma_dest += copy_size;
-		/* Insert the link descriptor to the LD ring */
-		list_add_tail(&new->node, &tx_list);
-	} while (len);
+			new->chunks = chunks--;
+			list_add_tail(&new->node, &tx_list);
+		} while (len);
+	}
 
 	if (new != first)
 		new->async_tx.cookie = -ENOSPC;
@@ -386,6 +489,77 @@
 	spin_unlock_bh(&sh_chan->desc_lock);
 
 	return &first->async_tx;
+
+err_get_desc:
+	list_for_each_entry(new, &tx_list, node)
+		new->mark = DESC_IDLE;
+	list_splice(&tx_list, &sh_chan->ld_free);
+
+	spin_unlock_bh(&sh_chan->desc_lock);
+
+	return NULL;
+}
+
+static struct dma_async_tx_descriptor *sh_dmae_prep_memcpy(
+	struct dma_chan *chan, dma_addr_t dma_dest, dma_addr_t dma_src,
+	size_t len, unsigned long flags)
+{
+	struct sh_dmae_chan *sh_chan;
+	struct scatterlist sg;
+
+	if (!chan || !len)
+		return NULL;
+
+	chan->private = NULL;
+
+	sh_chan = to_sh_chan(chan);
+
+	sg_init_table(&sg, 1);
+	sg_set_page(&sg, pfn_to_page(PFN_DOWN(dma_src)), len,
+		    offset_in_page(dma_src));
+	sg_dma_address(&sg) = dma_src;
+	sg_dma_len(&sg) = len;
+
+	return sh_dmae_prep_sg(sh_chan, &sg, 1, &dma_dest, DMA_BIDIRECTIONAL,
+			       flags);
+}
+
+static struct dma_async_tx_descriptor *sh_dmae_prep_slave_sg(
+	struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len,
+	enum dma_data_direction direction, unsigned long flags)
+{
+	struct sh_dmae_slave *param;
+	struct sh_dmae_chan *sh_chan;
+
+	if (!chan)
+		return NULL;
+
+	sh_chan = to_sh_chan(chan);
+	param = chan->private;
+
+	/* Someone calling slave DMA on a public channel? */
+	if (!param || !sg_len) {
+		dev_warn(sh_chan->dev, "%s: bad parameter: %p, %d, %d\n",
+			 __func__, param, sg_len, param ? param->slave_id : -1);
+		return NULL;
+	}
+
+	/*
+	 * if (param != NULL), this is a successfully requested slave channel,
+	 * therefore param->config != NULL too.
+	 */
+	return sh_dmae_prep_sg(sh_chan, sgl, sg_len, &param->config->addr,
+			       direction, flags);
+}
+
+static void sh_dmae_terminate_all(struct dma_chan *chan)
+{
+	struct sh_dmae_chan *sh_chan = to_sh_chan(chan);
+
+	if (!chan)
+		return;
+
+	sh_dmae_chan_ld_cleanup(sh_chan, true);
 }
 
 static dma_async_tx_callback __ld_cleanup(struct sh_dmae_chan *sh_chan, bool all)
@@ -419,7 +593,11 @@
 			cookie = tx->cookie;
 
 		if (desc->mark == DESC_COMPLETED && desc->chunks == 1) {
-			BUG_ON(sh_chan->completed_cookie != desc->cookie - 1);
+			if (sh_chan->completed_cookie != desc->cookie - 1)
+				dev_dbg(sh_chan->dev,
+					"Completing cookie %d, expected %d\n",
+					desc->cookie,
+					sh_chan->completed_cookie + 1);
 			sh_chan->completed_cookie = desc->cookie;
 		}
 
@@ -492,7 +670,7 @@
 		return;
 	}
 
-	/* Find the first un-transfer desciptor */
+	/* Find the first not transferred desciptor */
 	list_for_each_entry(sd, &sh_chan->ld_queue, node)
 		if (sd->mark == DESC_SUBMITTED) {
 			/* Get the ld start address from ld_queue */
@@ -559,7 +737,7 @@
 
 	/* IRQ Multi */
 	if (shdev->pdata.mode & SHDMA_MIX_IRQ) {
-		int cnt = 0;
+		int __maybe_unused cnt = 0;
 		switch (irq) {
 #if defined(DMTE6_IRQ) && defined(DMAE1_IRQ)
 		case DMTE6_IRQ:
@@ -596,11 +774,14 @@
 	struct sh_dmae_chan *sh_chan = (struct sh_dmae_chan *)data;
 	struct sh_desc *desc;
 	u32 sar_buf = sh_dmae_readl(sh_chan, SAR);
+	u32 dar_buf = sh_dmae_readl(sh_chan, DAR);
 
 	spin_lock(&sh_chan->desc_lock);
 	list_for_each_entry(desc, &sh_chan->ld_queue, node) {
-		if ((desc->hw.sar + desc->hw.tcr) == sar_buf &&
-		    desc->mark == DESC_SUBMITTED) {
+		if (desc->mark == DESC_SUBMITTED &&
+		    ((desc->direction == DMA_FROM_DEVICE &&
+		      (desc->hw.dar + desc->hw.tcr) == dar_buf) ||
+		     (desc->hw.sar + desc->hw.tcr) == sar_buf)) {
 			dev_dbg(sh_chan->dev, "done #%d@%p dst %u\n",
 				desc->async_tx.cookie, &desc->async_tx,
 				desc->hw.dar);
@@ -673,7 +854,7 @@
 	}
 
 	snprintf(new_sh_chan->dev_id, sizeof(new_sh_chan->dev_id),
-			"sh-dmae%d", new_sh_chan->id);
+		 "sh-dmae%d", new_sh_chan->id);
 
 	/* set up channel irq */
 	err = request_irq(irq, &sh_dmae_interrupt, irqflags,
@@ -684,11 +865,6 @@
 		goto err_no_irq;
 	}
 
-	/* CHCR register control function */
-	new_sh_chan->set_chcr = dmae_set_chcr;
-	/* DMARS register control function */
-	new_sh_chan->set_dmars = dmae_set_dmars;
-
 	shdev->chan[id] = new_sh_chan;
 	return 0;
 
@@ -759,12 +935,19 @@
 	INIT_LIST_HEAD(&shdev->common.channels);
 
 	dma_cap_set(DMA_MEMCPY, shdev->common.cap_mask);
+	dma_cap_set(DMA_SLAVE, shdev->common.cap_mask);
+
 	shdev->common.device_alloc_chan_resources
 		= sh_dmae_alloc_chan_resources;
 	shdev->common.device_free_chan_resources = sh_dmae_free_chan_resources;
 	shdev->common.device_prep_dma_memcpy = sh_dmae_prep_memcpy;
 	shdev->common.device_is_tx_complete = sh_dmae_is_complete;
 	shdev->common.device_issue_pending = sh_dmae_memcpy_issue_pending;
+
+	/* Compulsory for DMA_SLAVE fields */
+	shdev->common.device_prep_slave_sg = sh_dmae_prep_slave_sg;
+	shdev->common.device_terminate_all = sh_dmae_terminate_all;
+
 	shdev->common.dev = &pdev->dev;
 	/* Default transfer size of 32 bytes requires 32-byte alignment */
 	shdev->common.copy_align = 5;
diff --git a/drivers/dma/shdma.h b/drivers/dma/shdma.h
index 108f1cf..7e227f3 100644
--- a/drivers/dma/shdma.h
+++ b/drivers/dma/shdma.h
@@ -29,6 +29,7 @@
 	struct sh_dmae_regs hw;
 	struct list_head node;
 	struct dma_async_tx_descriptor async_tx;
+	enum dma_data_direction direction;
 	dma_cookie_t cookie;
 	int chunks;
 	int mark;
@@ -45,13 +46,9 @@
 	struct device *dev;		/* Channel device */
 	struct tasklet_struct tasklet;	/* Tasklet */
 	int descs_allocated;		/* desc count */
+	int xmit_shift;			/* log_2(bytes_per_xfer) */
 	int id;				/* Raw id of this channel */
 	char dev_id[16];		/* unique name per DMAC of channel */
-
-	/* Set chcr */
-	int (*set_chcr)(struct sh_dmae_chan *sh_chan, u32 regs);
-	/* Set DMA resource */
-	int (*set_dmars)(struct sh_dmae_chan *sh_chan, u16 res);
 };
 
 struct sh_dmae_device {
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 677cd53..bb64656 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -457,10 +457,10 @@
 
 config MTD_NAND_SH_FLCTL
 	tristate "Support for NAND on Renesas SuperH FLCTL"
-	depends on MTD_NAND && SUPERH && CPU_SUBTYPE_SH7723
+	depends on MTD_NAND && SUPERH
 	help
 	  Several Renesas SuperH CPU has FLCTL. This option enables support
-	  for NAND Flash using FLCTL. This driver support SH7723.
+	  for NAND Flash using FLCTL.
 
 config MTD_NAND_DAVINCI
         tristate "Support NAND on DaVinci SoC"
diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/sh_flctl.c
index 02bef21..1842df8 100644
--- a/drivers/mtd/nand/sh_flctl.c
+++ b/drivers/mtd/nand/sh_flctl.c
@@ -1,10 +1,10 @@
 /*
  * SuperH FLCTL nand controller
  *
- * Copyright © 2008 Renesas Solutions Corp.
- * Copyright © 2008 Atom Create Engineering Co., Ltd.
+ * Copyright (c) 2008 Renesas Solutions Corp.
+ * Copyright (c) 2008 Atom Create Engineering Co., Ltd.
  *
- * Based on fsl_elbc_nand.c, Copyright © 2006-2007 Freescale Semiconductor
+ * Based on fsl_elbc_nand.c, Copyright (c) 2006-2007 Freescale Semiconductor
  *
  * 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
@@ -75,6 +75,11 @@
 	writeb(TRSTRT, FLTRCR(flctl));
 }
 
+static void timeout_error(struct sh_flctl *flctl, const char *str)
+{
+	dev_err(&flctl->pdev->dev, "Timeout occured in %s\n", str);
+}
+
 static void wait_completion(struct sh_flctl *flctl)
 {
 	uint32_t timeout = LOOP_TIMEOUT_MAX;
@@ -87,7 +92,7 @@
 		udelay(1);
 	}
 
-	printk(KERN_ERR "wait_completion(): Timeout occured \n");
+	timeout_error(flctl, __func__);
 	writeb(0x0, FLTRCR(flctl));
 }
 
@@ -100,6 +105,8 @@
 		addr = page_addr;	/* ERASE1 */
 	} else if (page_addr != -1) {
 		/* SEQIN, READ0, etc.. */
+		if (flctl->chip.options & NAND_BUSWIDTH_16)
+			column >>= 1;
 		if (flctl->page_size) {
 			addr = column & 0x0FFF;
 			addr |= (page_addr & 0xff) << 16;
@@ -132,7 +139,7 @@
 			return;
 		udelay(1);
 	}
-	printk(KERN_ERR "wait_rfifo_ready(): Timeout occured \n");
+	timeout_error(flctl, __func__);
 }
 
 static void wait_wfifo_ready(struct sh_flctl *flctl)
@@ -146,7 +153,7 @@
 			return;
 		udelay(1);
 	}
-	printk(KERN_ERR "wait_wfifo_ready(): Timeout occured \n");
+	timeout_error(flctl, __func__);
 }
 
 static int wait_recfifo_ready(struct sh_flctl *flctl, int sector_number)
@@ -198,7 +205,7 @@
 		writel(0, FL4ECCCR(flctl));
 	}
 
-	printk(KERN_ERR "wait_recfifo_ready(): Timeout occured \n");
+	timeout_error(flctl, __func__);
 	return 1;	/* timeout */
 }
 
@@ -214,7 +221,7 @@
 			return;
 		udelay(1);
 	}
-	printk(KERN_ERR "wait_wecfifo_ready(): Timeout occured \n");
+	timeout_error(flctl, __func__);
 }
 
 static void read_datareg(struct sh_flctl *flctl, int offset)
@@ -275,7 +282,7 @@
 static void set_cmd_regs(struct mtd_info *mtd, uint32_t cmd, uint32_t flcmcdr_val)
 {
 	struct sh_flctl *flctl = mtd_to_flctl(mtd);
-	uint32_t flcmncr_val = readl(FLCMNCR(flctl));
+	uint32_t flcmncr_val = readl(FLCMNCR(flctl)) & ~SEL_16BIT;
 	uint32_t flcmdcr_val, addr_len_bytes = 0;
 
 	/* Set SNAND bit if page size is 2048byte */
@@ -297,6 +304,8 @@
 	case NAND_CMD_READOOB:
 		addr_len_bytes = flctl->rw_ADRCNT;
 		flcmdcr_val |= CDSRC_E;
+		if (flctl->chip.options & NAND_BUSWIDTH_16)
+			flcmncr_val |= SEL_16BIT;
 		break;
 	case NAND_CMD_SEQIN:
 		/* This case is that cmd is READ0 or READ1 or READ00 */
@@ -305,6 +314,8 @@
 	case NAND_CMD_PAGEPROG:
 		addr_len_bytes = flctl->rw_ADRCNT;
 		flcmdcr_val |= DOCMD2_E | CDSRC_E | SELRW;
+		if (flctl->chip.options & NAND_BUSWIDTH_16)
+			flcmncr_val |= SEL_16BIT;
 		break;
 	case NAND_CMD_READID:
 		flcmncr_val &= ~SNAND_E;
@@ -523,6 +534,8 @@
 		set_addr(mtd, 0, page_addr);
 
 		flctl->read_bytes = mtd->writesize + mtd->oobsize;
+		if (flctl->chip.options & NAND_BUSWIDTH_16)
+			column >>= 1;
 		flctl->index += column;
 		goto read_normal_exit;
 
@@ -686,6 +699,18 @@
 	return data;
 }
 
+static uint16_t flctl_read_word(struct mtd_info *mtd)
+{
+       struct sh_flctl *flctl = mtd_to_flctl(mtd);
+       int index = flctl->index;
+       uint16_t data;
+       uint16_t *buf = (uint16_t *)&flctl->done_buff[index];
+
+       data = *buf;
+       flctl->index += 2;
+       return data;
+}
+
 static void flctl_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 {
 	int i;
@@ -769,38 +794,36 @@
 	return 0;
 }
 
-static int __init flctl_probe(struct platform_device *pdev)
+static int __devinit flctl_probe(struct platform_device *pdev)
 {
 	struct resource *res;
 	struct sh_flctl *flctl;
 	struct mtd_info *flctl_mtd;
 	struct nand_chip *nand;
 	struct sh_flctl_platform_data *pdata;
-	int ret;
+	int ret = -ENXIO;
 
 	pdata = pdev->dev.platform_data;
 	if (pdata == NULL) {
-		printk(KERN_ERR "sh_flctl platform_data not found.\n");
-		return -ENODEV;
+		dev_err(&pdev->dev, "no platform data defined\n");
+		return -EINVAL;
 	}
 
 	flctl = kzalloc(sizeof(struct sh_flctl), GFP_KERNEL);
 	if (!flctl) {
-		printk(KERN_ERR "Unable to allocate NAND MTD dev structure.\n");
+		dev_err(&pdev->dev, "failed to allocate driver data\n");
 		return -ENOMEM;
 	}
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
-		printk(KERN_ERR "%s: resource not found.\n", __func__);
-		ret = -ENODEV;
+		dev_err(&pdev->dev, "failed to get I/O memory\n");
 		goto err;
 	}
 
-	flctl->reg = ioremap(res->start, res->end - res->start + 1);
+	flctl->reg = ioremap(res->start, resource_size(res));
 	if (flctl->reg == NULL) {
-		printk(KERN_ERR "%s: ioremap error.\n", __func__);
-		ret = -ENOMEM;
+		dev_err(&pdev->dev, "failed to remap I/O memory\n");
 		goto err;
 	}
 
@@ -808,6 +831,7 @@
 	flctl_mtd = &flctl->mtd;
 	nand = &flctl->chip;
 	flctl_mtd->priv = nand;
+	flctl->pdev = pdev;
 	flctl->hwecc = pdata->has_hwecc;
 
 	flctl_register_init(flctl, pdata->flcmncr_val);
@@ -825,6 +849,11 @@
 	nand->select_chip = flctl_select_chip;
 	nand->cmdfunc = flctl_cmdfunc;
 
+	if (pdata->flcmncr_val & SEL_16BIT) {
+		nand->options |= NAND_BUSWIDTH_16;
+		nand->read_word = flctl_read_word;
+	}
+
 	ret = nand_scan_ident(flctl_mtd, 1);
 	if (ret)
 		goto err;
@@ -846,7 +875,7 @@
 	return ret;
 }
 
-static int __exit flctl_remove(struct platform_device *pdev)
+static int __devexit flctl_remove(struct platform_device *pdev)
 {
 	struct sh_flctl *flctl = platform_get_drvdata(pdev);
 
diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h
index 0efcded..f7d2589 100644
--- a/drivers/serial/sh-sci.h
+++ b/drivers/serial/sh-sci.h
@@ -518,34 +518,6 @@
 {
 	if (port->mapbase == 0xfffffe80)
 		return __raw_readb(SCPDR)&0x01 ? 1 : 0; /* SCI */
-	if (port->mapbase == 0xa4000150)
-		return __raw_readb(SCPDR)&0x10 ? 1 : 0; /* SCIF */
-	if (port->mapbase == 0xa4000140)
-		return __raw_readb(SCPDR)&0x04 ? 1 : 0; /* IRDA */
-	return 1;
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7705)
-static inline int sci_rxd_in(struct uart_port *port)
-{
-	if (port->mapbase == SCIF0)
-		return __raw_readb(SCPDR)&0x04 ? 1 : 0; /* IRDA */
-	if (port->mapbase == SCIF2)
-		return __raw_readb(SCPDR)&0x10 ? 1 : 0; /* SCIF */
-	return 1;
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712)
-static inline int sci_rxd_in(struct uart_port *port)
-{
-	  return sci_in(port,SCxSR)&0x0010 ? 1 : 0;
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7720) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7721)
-static inline int sci_rxd_in(struct uart_port *port)
-{
-	if (port->mapbase == 0xa4430000)
-		return sci_in(port, SCxSR) & 0x0003 ? 1 : 0;
-	else if (port->mapbase == 0xa4438000)
-		return sci_in(port, SCxSR) & 0x0003 ? 1 : 0;
 	return 1;
 }
 #elif defined(CONFIG_CPU_SUBTYPE_SH7750)  || \
@@ -558,207 +530,17 @@
 {
 	if (port->mapbase == 0xffe00000)
 		return __raw_readb(SCSPTR1)&0x01 ? 1 : 0; /* SCI */
-	if (port->mapbase == 0xffe80000)
-		return __raw_readw(SCSPTR2)&0x0001 ? 1 : 0; /* SCIF */
 	return 1;
 }
-#elif defined(CONFIG_CPU_SUBTYPE_SH4_202)
-static inline int sci_rxd_in(struct uart_port *port)
-{
-	if (port->mapbase == 0xffe80000)
-		return __raw_readw(SCSPTR2)&0x0001 ? 1 : 0; /* SCIF */
-	return 1;
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7757)
-static inline int sci_rxd_in(struct uart_port *port)
-{
-	if (port->mapbase == 0xfe4b0000)
-		return __raw_readw(SCSPTR0) & 0x0001 ? 1 : 0;
-	if (port->mapbase == 0xfe4c0000)
-		return __raw_readw(SCSPTR1) & 0x0001 ? 1 : 0;
-	if (port->mapbase == 0xfe4d0000)
-		return __raw_readw(SCSPTR2) & 0x0001 ? 1 : 0;
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7760)
-static inline int sci_rxd_in(struct uart_port *port)
-{
-	if (port->mapbase == 0xfe600000)
-		return __raw_readw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */
-	if (port->mapbase == 0xfe610000)
-		return __raw_readw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
-	if (port->mapbase == 0xfe620000)
-		return __raw_readw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */
-	return 1;
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7343)
-static inline int sci_rxd_in(struct uart_port *port)
-{
-	if (port->mapbase == 0xffe00000)
-		return __raw_readw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */
-	if (port->mapbase == 0xffe10000)
-		return __raw_readw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
-	if (port->mapbase == 0xffe20000)
-		return __raw_readw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */
-	if (port->mapbase == 0xffe30000)
-		return __raw_readw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */
-	return 1;
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7366)
-static inline int sci_rxd_in(struct uart_port *port)
-{
-	if (port->mapbase == 0xffe00000)
-		return __raw_readb(SCPDR0) & 0x0001 ? 1 : 0; /* SCIF0 */
-	return 1;
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7722)
-static inline int sci_rxd_in(struct uart_port *port)
-{
-	if (port->mapbase == 0xffe00000)
-		return __raw_readb(PSDR) & 0x02 ? 1 : 0; /* SCIF0 */
-	if (port->mapbase == 0xffe10000)
-		return __raw_readb(PADR) & 0x40 ? 1 : 0; /* SCIF1 */
-	if (port->mapbase == 0xffe20000)
-		return __raw_readb(PWDR) & 0x04 ? 1 : 0; /* SCIF2 */
-
-	return 1;
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7723)
-static inline int sci_rxd_in(struct uart_port *port)
-{
-        if (port->mapbase == 0xffe00000)
-                return __raw_readb(SCSPTR0) & 0x0008 ? 1 : 0; /* SCIF0 */
-        if (port->mapbase == 0xffe10000)
-                return __raw_readb(SCSPTR1) & 0x0020 ? 1 : 0; /* SCIF1 */
-        if (port->mapbase == 0xffe20000)
-                return __raw_readb(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF2 */
-        if (port->mapbase == 0xa4e30000)
-                return __raw_readb(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF3 */
-        if (port->mapbase == 0xa4e40000)
-                return __raw_readb(SCSPTR4) & 0x0001 ? 1 : 0; /* SCIF4 */
-        if (port->mapbase == 0xa4e50000)
-                return __raw_readb(SCSPTR5) & 0x0008 ? 1 : 0; /* SCIF5 */
-        return 1;
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7724)
-#  define SCFSR    0x0010
-#  define SCASSR   0x0014
-static inline int sci_rxd_in(struct uart_port *port)
-{
-	if (port->type == PORT_SCIF)
-		return __raw_readw((port->mapbase + SCFSR))  & SCIF_BRK ? 1 : 0;
-	if (port->type == PORT_SCIFA)
-		return __raw_readw((port->mapbase + SCASSR)) & SCIF_BRK ? 1 : 0;
-	return 1;
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103)
-static inline int sci_rxd_in(struct uart_port *port)
-{
-         return sci_in(port, SCSPTR)&0x0001 ? 1 : 0; /* SCIF */
-}
 #elif defined(__H8300H__) || defined(__H8300S__)
 static inline int sci_rxd_in(struct uart_port *port)
 {
 	int ch = (port->mapbase - SMR0) >> 3;
 	return (H8300_SCI_DR(ch) & h8300_sci_pins[ch].rx) ? 1 : 0;
 }
-#elif defined(CONFIG_CPU_SUBTYPE_SH7763)
+#else /* default case for non-SCI processors */
 static inline int sci_rxd_in(struct uart_port *port)
 {
-	if (port->mapbase == 0xffe00000)
-		return __raw_readw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */
-	if (port->mapbase == 0xffe08000)
-		return __raw_readw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
-	if (port->mapbase == 0xffe10000)
-		return __raw_readw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF/IRDA */
-
-	return 1;
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7770)
-static inline int sci_rxd_in(struct uart_port *port)
-{
-	if (port->mapbase == 0xff923000)
-		return __raw_readw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */
-	if (port->mapbase == 0xff924000)
-		return __raw_readw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
-	if (port->mapbase == 0xff925000)
-		return __raw_readw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */
-	return 1;
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
-static inline int sci_rxd_in(struct uart_port *port)
-{
-	if (port->mapbase == 0xffe00000)
-		return __raw_readw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */
-	if (port->mapbase == 0xffe10000)
-		return __raw_readw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
-	return 1;
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7785) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7786)
-static inline int sci_rxd_in(struct uart_port *port)
-{
-	if (port->mapbase == 0xffea0000)
-		return __raw_readw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */
-	if (port->mapbase == 0xffeb0000)
-		return __raw_readw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
-	if (port->mapbase == 0xffec0000)
-		return __raw_readw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */
-	if (port->mapbase == 0xffed0000)
-		return __raw_readw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */
-	if (port->mapbase == 0xffee0000)
-		return __raw_readw(SCSPTR4) & 0x0001 ? 1 : 0; /* SCIF */
-	if (port->mapbase == 0xffef0000)
-		return __raw_readw(SCSPTR5) & 0x0001 ? 1 : 0; /* SCIF */
-	return 1;
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7201) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7203) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7206) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7263)
-static inline int sci_rxd_in(struct uart_port *port)
-{
-	if (port->mapbase == 0xfffe8000)
-		return __raw_readw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */
-	if (port->mapbase == 0xfffe8800)
-		return __raw_readw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
-	if (port->mapbase == 0xfffe9000)
-		return __raw_readw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */
-	if (port->mapbase == 0xfffe9800)
-		return __raw_readw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */
-#if defined(CONFIG_CPU_SUBTYPE_SH7201)
-	if (port->mapbase == 0xfffeA000)
-		return __raw_readw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */
-	if (port->mapbase == 0xfffeA800)
-		return __raw_readw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
-	if (port->mapbase == 0xfffeB000)
-		return __raw_readw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */
-	if (port->mapbase == 0xfffeB800)
-		return __raw_readw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */
-#endif
-	return 1;
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7619)
-static inline int sci_rxd_in(struct uart_port *port)
-{
-	if (port->mapbase == 0xf8400000)
-		return __raw_readw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */
-	if (port->mapbase == 0xf8410000)
-		return __raw_readw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
-	if (port->mapbase == 0xf8420000)
-		return __raw_readw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */
-	return 1;
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SHX3)
-static inline int sci_rxd_in(struct uart_port *port)
-{
-	if (port->mapbase == 0xffc30000)
-		return __raw_readw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */
-	if (port->mapbase == 0xffc40000)
-		return __raw_readw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
-	if (port->mapbase == 0xffc50000)
-		return __raw_readw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */
-	if (port->mapbase == 0xffc60000)
-		return __raw_readw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */
 	return 1;
 }
 #endif
diff --git a/drivers/sh/intc.c b/drivers/sh/intc.c
index d5d7f23..3a5a17d 100644
--- a/drivers/sh/intc.c
+++ b/drivers/sh/intc.c
@@ -259,6 +259,43 @@
 	}
 }
 
+static void (*intc_enable_noprio_fns[])(unsigned long addr,
+					unsigned long handle,
+					void (*fn)(unsigned long,
+						   unsigned long,
+						   unsigned long),
+					unsigned int irq) = {
+	[MODE_ENABLE_REG] = intc_mode_field,
+	[MODE_MASK_REG] = intc_mode_zero,
+	[MODE_DUAL_REG] = intc_mode_field,
+	[MODE_PRIO_REG] = intc_mode_field,
+	[MODE_PCLR_REG] = intc_mode_field,
+};
+
+static void intc_enable_disable(struct intc_desc_int *d,
+				unsigned long handle, int do_enable)
+{
+	unsigned long addr;
+	unsigned int cpu;
+	void (*fn)(unsigned long, unsigned long,
+		   void (*)(unsigned long, unsigned long, unsigned long),
+		   unsigned int);
+
+	if (do_enable) {
+		for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_E(handle)); cpu++) {
+			addr = INTC_REG(d, _INTC_ADDR_E(handle), cpu);
+			fn = intc_enable_noprio_fns[_INTC_MODE(handle)];
+			fn(addr, handle, intc_reg_fns[_INTC_FN(handle)], 0);
+		}
+	} else {
+		for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_D(handle)); cpu++) {
+			addr = INTC_REG(d, _INTC_ADDR_D(handle), cpu);
+			fn = intc_disable_fns[_INTC_MODE(handle)];
+			fn(addr, handle, intc_reg_fns[_INTC_FN(handle)], 0);
+		}
+	}
+}
+
 static int intc_set_wake(unsigned int irq, unsigned int on)
 {
 	return 0; /* allow wakeup, but setup hardware in intc_suspend() */
@@ -400,11 +437,11 @@
 static intc_enum __init intc_grp_id(struct intc_desc *desc,
 				    intc_enum enum_id)
 {
-	struct intc_group *g = desc->groups;
+	struct intc_group *g = desc->hw.groups;
 	unsigned int i, j;
 
-	for (i = 0; g && enum_id && i < desc->nr_groups; i++) {
-		g = desc->groups + i;
+	for (i = 0; g && enum_id && i < desc->hw.nr_groups; i++) {
+		g = desc->hw.groups + i;
 
 		for (j = 0; g->enum_ids[j]; j++) {
 			if (g->enum_ids[j] != enum_id)
@@ -417,19 +454,21 @@
 	return 0;
 }
 
-static unsigned int __init intc_mask_data(struct intc_desc *desc,
-					  struct intc_desc_int *d,
-					  intc_enum enum_id, int do_grps)
+static unsigned int __init _intc_mask_data(struct intc_desc *desc,
+					   struct intc_desc_int *d,
+					   intc_enum enum_id,
+					   unsigned int *reg_idx,
+					   unsigned int *fld_idx)
 {
-	struct intc_mask_reg *mr = desc->mask_regs;
-	unsigned int i, j, fn, mode;
+	struct intc_mask_reg *mr = desc->hw.mask_regs;
+	unsigned int fn, mode;
 	unsigned long reg_e, reg_d;
 
-	for (i = 0; mr && enum_id && i < desc->nr_mask_regs; i++) {
-		mr = desc->mask_regs + i;
+	while (mr && enum_id && *reg_idx < desc->hw.nr_mask_regs) {
+		mr = desc->hw.mask_regs + *reg_idx;
 
-		for (j = 0; j < ARRAY_SIZE(mr->enum_ids); j++) {
-			if (mr->enum_ids[j] != enum_id)
+		for (; *fld_idx < ARRAY_SIZE(mr->enum_ids); (*fld_idx)++) {
+			if (mr->enum_ids[*fld_idx] != enum_id)
 				continue;
 
 			if (mr->set_reg && mr->clr_reg) {
@@ -455,29 +494,49 @@
 					intc_get_reg(d, reg_e),
 					intc_get_reg(d, reg_d),
 					1,
-					(mr->reg_width - 1) - j);
+					(mr->reg_width - 1) - *fld_idx);
 		}
+
+		*fld_idx = 0;
+		(*reg_idx)++;
 	}
 
+	return 0;
+}
+
+static unsigned int __init intc_mask_data(struct intc_desc *desc,
+					  struct intc_desc_int *d,
+					  intc_enum enum_id, int do_grps)
+{
+	unsigned int i = 0;
+	unsigned int j = 0;
+	unsigned int ret;
+
+	ret = _intc_mask_data(desc, d, enum_id, &i, &j);
+	if (ret)
+		return ret;
+
 	if (do_grps)
 		return intc_mask_data(desc, d, intc_grp_id(desc, enum_id), 0);
 
 	return 0;
 }
 
-static unsigned int __init intc_prio_data(struct intc_desc *desc,
-					  struct intc_desc_int *d,
-					  intc_enum enum_id, int do_grps)
+static unsigned int __init _intc_prio_data(struct intc_desc *desc,
+					   struct intc_desc_int *d,
+					   intc_enum enum_id,
+					   unsigned int *reg_idx,
+					   unsigned int *fld_idx)
 {
-	struct intc_prio_reg *pr = desc->prio_regs;
-	unsigned int i, j, fn, mode, bit;
+	struct intc_prio_reg *pr = desc->hw.prio_regs;
+	unsigned int fn, n, mode, bit;
 	unsigned long reg_e, reg_d;
 
-	for (i = 0; pr && enum_id && i < desc->nr_prio_regs; i++) {
-		pr = desc->prio_regs + i;
+	while (pr && enum_id && *reg_idx < desc->hw.nr_prio_regs) {
+		pr = desc->hw.prio_regs + *reg_idx;
 
-		for (j = 0; j < ARRAY_SIZE(pr->enum_ids); j++) {
-			if (pr->enum_ids[j] != enum_id)
+		for (; *fld_idx < ARRAY_SIZE(pr->enum_ids); (*fld_idx)++) {
+			if (pr->enum_ids[*fld_idx] != enum_id)
 				continue;
 
 			if (pr->set_reg && pr->clr_reg) {
@@ -495,34 +554,79 @@
 			}
 
 			fn += (pr->reg_width >> 3) - 1;
+			n = *fld_idx + 1;
 
-			BUG_ON((j + 1) * pr->field_width > pr->reg_width);
+			BUG_ON(n * pr->field_width > pr->reg_width);
 
-			bit = pr->reg_width - ((j + 1) * pr->field_width);
+			bit = pr->reg_width - (n * pr->field_width);
 
 			return _INTC_MK(fn, mode,
 					intc_get_reg(d, reg_e),
 					intc_get_reg(d, reg_d),
 					pr->field_width, bit);
 		}
+
+		*fld_idx = 0;
+		(*reg_idx)++;
 	}
 
+	return 0;
+}
+
+static unsigned int __init intc_prio_data(struct intc_desc *desc,
+					  struct intc_desc_int *d,
+					  intc_enum enum_id, int do_grps)
+{
+	unsigned int i = 0;
+	unsigned int j = 0;
+	unsigned int ret;
+
+	ret = _intc_prio_data(desc, d, enum_id, &i, &j);
+	if (ret)
+		return ret;
+
 	if (do_grps)
 		return intc_prio_data(desc, d, intc_grp_id(desc, enum_id), 0);
 
 	return 0;
 }
 
+static void __init intc_enable_disable_enum(struct intc_desc *desc,
+					    struct intc_desc_int *d,
+					    intc_enum enum_id, int enable)
+{
+	unsigned int i, j, data;
+
+	/* go through and enable/disable all mask bits */
+	i = j = 0;
+	do {
+		data = _intc_mask_data(desc, d, enum_id, &i, &j);
+		if (data)
+			intc_enable_disable(d, data, enable);
+		j++;
+	} while (data);
+
+	/* go through and enable/disable all priority fields */
+	i = j = 0;
+	do {
+		data = _intc_prio_data(desc, d, enum_id, &i, &j);
+		if (data)
+			intc_enable_disable(d, data, enable);
+
+		j++;
+	} while (data);
+}
+
 static unsigned int __init intc_ack_data(struct intc_desc *desc,
 					  struct intc_desc_int *d,
 					  intc_enum enum_id)
 {
-	struct intc_mask_reg *mr = desc->ack_regs;
+	struct intc_mask_reg *mr = desc->hw.ack_regs;
 	unsigned int i, j, fn, mode;
 	unsigned long reg_e, reg_d;
 
-	for (i = 0; mr && enum_id && i < desc->nr_ack_regs; i++) {
-		mr = desc->ack_regs + i;
+	for (i = 0; mr && enum_id && i < desc->hw.nr_ack_regs; i++) {
+		mr = desc->hw.ack_regs + i;
 
 		for (j = 0; j < ARRAY_SIZE(mr->enum_ids); j++) {
 			if (mr->enum_ids[j] != enum_id)
@@ -549,11 +653,11 @@
 					   struct intc_desc_int *d,
 					   intc_enum enum_id)
 {
-	struct intc_sense_reg *sr = desc->sense_regs;
+	struct intc_sense_reg *sr = desc->hw.sense_regs;
 	unsigned int i, j, fn, bit;
 
-	for (i = 0; sr && enum_id && i < desc->nr_sense_regs; i++) {
-		sr = desc->sense_regs + i;
+	for (i = 0; sr && enum_id && i < desc->hw.nr_sense_regs; i++) {
+		sr = desc->hw.sense_regs + i;
 
 		for (j = 0; j < ARRAY_SIZE(sr->enum_ids); j++) {
 			if (sr->enum_ids[j] != enum_id)
@@ -656,7 +760,7 @@
 	/* irq should be disabled by default */
 	d->chip.mask(irq);
 
-	if (desc->ack_regs)
+	if (desc->hw.ack_regs)
 		ack_handle[irq] = intc_ack_data(desc, d, enum_id);
 }
 
@@ -684,6 +788,7 @@
 void __init register_intc_controller(struct intc_desc *desc)
 {
 	unsigned int i, k, smp;
+	struct intc_hw_desc *hw = &desc->hw;
 	struct intc_desc_int *d;
 
 	d = kzalloc(sizeof(*d), GFP_NOWAIT);
@@ -691,10 +796,10 @@
 	INIT_LIST_HEAD(&d->list);
 	list_add(&d->list, &intc_list);
 
-	d->nr_reg = desc->mask_regs ? desc->nr_mask_regs * 2 : 0;
-	d->nr_reg += desc->prio_regs ? desc->nr_prio_regs * 2 : 0;
-	d->nr_reg += desc->sense_regs ? desc->nr_sense_regs : 0;
-	d->nr_reg += desc->ack_regs ? desc->nr_ack_regs : 0;
+	d->nr_reg = hw->mask_regs ? hw->nr_mask_regs * 2 : 0;
+	d->nr_reg += hw->prio_regs ? hw->nr_prio_regs * 2 : 0;
+	d->nr_reg += hw->sense_regs ? hw->nr_sense_regs : 0;
+	d->nr_reg += hw->ack_regs ? hw->nr_ack_regs : 0;
 
 	d->reg = kzalloc(d->nr_reg * sizeof(*d->reg), GFP_NOWAIT);
 #ifdef CONFIG_SMP
@@ -702,30 +807,31 @@
 #endif
 	k = 0;
 
-	if (desc->mask_regs) {
-		for (i = 0; i < desc->nr_mask_regs; i++) {
-			smp = IS_SMP(desc->mask_regs[i]);
-			k += save_reg(d, k, desc->mask_regs[i].set_reg, smp);
-			k += save_reg(d, k, desc->mask_regs[i].clr_reg, smp);
+	if (hw->mask_regs) {
+		for (i = 0; i < hw->nr_mask_regs; i++) {
+			smp = IS_SMP(hw->mask_regs[i]);
+			k += save_reg(d, k, hw->mask_regs[i].set_reg, smp);
+			k += save_reg(d, k, hw->mask_regs[i].clr_reg, smp);
 		}
 	}
 
-	if (desc->prio_regs) {
-		d->prio = kzalloc(desc->nr_vectors * sizeof(*d->prio), GFP_NOWAIT);
+	if (hw->prio_regs) {
+		d->prio = kzalloc(hw->nr_vectors * sizeof(*d->prio),
+				  GFP_NOWAIT);
 
-		for (i = 0; i < desc->nr_prio_regs; i++) {
-			smp = IS_SMP(desc->prio_regs[i]);
-			k += save_reg(d, k, desc->prio_regs[i].set_reg, smp);
-			k += save_reg(d, k, desc->prio_regs[i].clr_reg, smp);
+		for (i = 0; i < hw->nr_prio_regs; i++) {
+			smp = IS_SMP(hw->prio_regs[i]);
+			k += save_reg(d, k, hw->prio_regs[i].set_reg, smp);
+			k += save_reg(d, k, hw->prio_regs[i].clr_reg, smp);
 		}
 	}
 
-	if (desc->sense_regs) {
-		d->sense = kzalloc(desc->nr_vectors * sizeof(*d->sense), GFP_NOWAIT);
+	if (hw->sense_regs) {
+		d->sense = kzalloc(hw->nr_vectors * sizeof(*d->sense),
+				   GFP_NOWAIT);
 
-		for (i = 0; i < desc->nr_sense_regs; i++) {
-			k += save_reg(d, k, desc->sense_regs[i].reg, 0);
-		}
+		for (i = 0; i < hw->nr_sense_regs; i++)
+			k += save_reg(d, k, hw->sense_regs[i].reg, 0);
 	}
 
 	d->chip.name = desc->name;
@@ -738,18 +844,26 @@
 	d->chip.set_type = intc_set_sense;
 	d->chip.set_wake = intc_set_wake;
 
-	if (desc->ack_regs) {
-		for (i = 0; i < desc->nr_ack_regs; i++)
-			k += save_reg(d, k, desc->ack_regs[i].set_reg, 0);
+	if (hw->ack_regs) {
+		for (i = 0; i < hw->nr_ack_regs; i++)
+			k += save_reg(d, k, hw->ack_regs[i].set_reg, 0);
 
 		d->chip.mask_ack = intc_mask_ack;
 	}
 
+	/* disable bits matching force_disable before registering irqs */
+	if (desc->force_disable)
+		intc_enable_disable_enum(desc, d, desc->force_disable, 0);
+
+	/* disable bits matching force_enable before registering irqs */
+	if (desc->force_enable)
+		intc_enable_disable_enum(desc, d, desc->force_enable, 0);
+
 	BUG_ON(k > 256); /* _INTC_ADDR_E() and _INTC_ADDR_D() are 8 bits */
 
 	/* register the vectors one by one */
-	for (i = 0; i < desc->nr_vectors; i++) {
-		struct intc_vect *vect = desc->vectors + i;
+	for (i = 0; i < hw->nr_vectors; i++) {
+		struct intc_vect *vect = hw->vectors + i;
 		unsigned int irq = evt2irq(vect->vect);
 		struct irq_desc *irq_desc;
 
@@ -764,8 +878,8 @@
 
 		intc_register_irq(desc, d, vect->enum_id, irq);
 
-		for (k = i + 1; k < desc->nr_vectors; k++) {
-			struct intc_vect *vect2 = desc->vectors + k;
+		for (k = i + 1; k < hw->nr_vectors; k++) {
+			struct intc_vect *vect2 = hw->vectors + k;
 			unsigned int irq2 = evt2irq(vect2->vect);
 
 			if (vect->enum_id != vect2->enum_id)
@@ -785,11 +899,15 @@
 			vect2->enum_id = 0;
 
 			/* redirect this interrupts to the first one */
-			set_irq_chip_and_handler_name(irq2, &d->chip,
-					intc_redirect_irq, "redirect");
+			set_irq_chip(irq2, &dummy_irq_chip);
+			set_irq_chained_handler(irq2, intc_redirect_irq);
 			set_irq_data(irq2, (void *)irq);
 		}
 	}
+
+	/* enable bits matching force_enable after registering irqs */
+	if (desc->force_enable)
+		intc_enable_disable_enum(desc, d, desc->force_enable, 1);
 }
 
 static int intc_suspend(struct sys_device *dev, pm_message_t state)
@@ -872,7 +990,7 @@
 /*
  * Dynamic IRQ allocation and deallocation
  */
-static unsigned int create_irq_on_node(unsigned int irq_want, int node)
+unsigned int create_irq_nr(unsigned int irq_want, int node)
 {
 	unsigned int irq = 0, new;
 	unsigned long flags;
@@ -881,24 +999,28 @@
 	spin_lock_irqsave(&vector_lock, flags);
 
 	/*
-	 * First try the wanted IRQ, then scan.
+	 * First try the wanted IRQ
 	 */
-	if (test_and_set_bit(irq_want, intc_irq_map)) {
+	if (test_and_set_bit(irq_want, intc_irq_map) == 0) {
+		new = irq_want;
+	} else {
+		/* .. then fall back to scanning. */
 		new = find_first_zero_bit(intc_irq_map, nr_irqs);
 		if (unlikely(new == nr_irqs))
 			goto out_unlock;
 
-		desc = irq_to_desc_alloc_node(new, node);
-		if (unlikely(!desc)) {
-			pr_info("can't get irq_desc for %d\n", new);
-			goto out_unlock;
-		}
-
-		desc = move_irq_desc(desc, node);
 		__set_bit(new, intc_irq_map);
-		irq = new;
 	}
 
+	desc = irq_to_desc_alloc_node(new, node);
+	if (unlikely(!desc)) {
+		pr_info("can't get irq_desc for %d\n", new);
+		goto out_unlock;
+	}
+
+	desc = move_irq_desc(desc, node);
+	irq = new;
+
 out_unlock:
 	spin_unlock_irqrestore(&vector_lock, flags);
 
@@ -913,7 +1035,7 @@
 	int nid = cpu_to_node(smp_processor_id());
 	int irq;
 
-	irq = create_irq_on_node(NR_IRQS_LEGACY, nid);
+	irq = create_irq_nr(NR_IRQS_LEGACY, nid);
 	if (irq == 0)
 		irq = -1;
 
diff --git a/drivers/sh/pfc.c b/drivers/sh/pfc.c
index 082604e..cf0303ac 100644
--- a/drivers/sh/pfc.c
+++ b/drivers/sh/pfc.c
@@ -337,12 +337,39 @@
 		if (!enum_id)
 			break;
 
+		/* first check if this is a function enum */
 		in_range = enum_in_range(enum_id, &gpioc->function);
-		if (!in_range && range) {
-			in_range = enum_in_range(enum_id, range);
+		if (!in_range) {
+			/* not a function enum */
+			if (range) {
+				/*
+				 * other range exists, so this pin is
+				 * a regular GPIO pin that now is being
+				 * bound to a specific direction.
+				 *
+				 * for this case we only allow function enums
+				 * and the enums that match the other range.
+				 */
+				in_range = enum_in_range(enum_id, range);
 
-			if (in_range && enum_id == range->force)
-				continue;
+				/*
+				 * special case pass through for fixed
+				 * input-only or output-only pins without
+				 * function enum register association.
+				 */
+				if (in_range && enum_id == range->force)
+					continue;
+			} else {
+				/*
+				 * no other range exists, so this pin
+				 * must then be of the function type.
+				 *
+				 * allow function type pins to select
+				 * any combination of function/in/out
+				 * in their MARK lists.
+				 */
+				in_range = 1;
+			}
 		}
 
 		if (!in_range)
diff --git a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c
index 53f8f11..f997510 100644
--- a/drivers/video/pvr2fb.c
+++ b/drivers/video/pvr2fb.c
@@ -831,7 +831,7 @@
 	printk(KERN_NOTICE "fb%d: registering with SQ API\n", fb_info->node);
 
 	pvr2fb_map = sq_remap(fb_info->fix.smem_start, fb_info->fix.smem_len,
-			      fb_info->fix.id, pgprot_val(PAGE_SHARED));
+			      fb_info->fix.id, PAGE_SHARED);
 
 	printk(KERN_NOTICE "fb%d: Mapped video memory to SQ addr 0x%lx\n",
 	       fb_info->node, pvr2fb_map);
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index a69830d..8d7653e 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -19,6 +19,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/interrupt.h>
 #include <linux/vmalloc.h>
+#include <linux/ioctl.h>
 #include <video/sh_mobile_lcdc.h>
 #include <asm/atomic.h>
 
@@ -106,6 +107,7 @@
 #define LDRCNTR_SRC	0x00010000
 #define LDRCNTR_MRS	0x00000002
 #define LDRCNTR_MRC	0x00000001
+#define LDSR_MRS	0x00000100
 
 struct sh_mobile_lcdc_priv;
 struct sh_mobile_lcdc_chan {
@@ -122,8 +124,8 @@
 	struct scatterlist *sglist;
 	unsigned long frame_end;
 	unsigned long pan_offset;
-	unsigned long new_pan_offset;
 	wait_queue_head_t frame_end_wait;
+	struct completion vsync_completion;
 };
 
 struct sh_mobile_lcdc_priv {
@@ -366,19 +368,8 @@
 		}
 
 		/* VSYNC End */
-		if (ldintr & LDINTR_VES) {
-			unsigned long ldrcntr = lcdc_read(priv, _LDRCNTR);
-			/* Set the source address for the next refresh */
-			lcdc_write_chan_mirror(ch, LDSA1R, ch->dma_handle +
-					       ch->new_pan_offset);
-			if (lcdc_chan_is_sublcd(ch))
-				lcdc_write(ch->lcdc, _LDRCNTR,
-					   ldrcntr ^ LDRCNTR_SRS);
-			else
-				lcdc_write(ch->lcdc, _LDRCNTR,
-					   ldrcntr ^ LDRCNTR_MRS);
-			ch->pan_offset = ch->new_pan_offset;
-		}
+		if (ldintr & LDINTR_VES)
+			complete(&ch->vsync_completion);
 	}
 
 	return IRQ_HANDLED;
@@ -767,25 +758,69 @@
 				     struct fb_info *info)
 {
 	struct sh_mobile_lcdc_chan *ch = info->par;
+	struct sh_mobile_lcdc_priv *priv = ch->lcdc;
+	unsigned long ldrcntr;
+	unsigned long new_pan_offset;
 
-	if (info->var.xoffset == var->xoffset &&
-	    info->var.yoffset == var->yoffset)
-		return 0;	/* No change, do nothing */
-
-	ch->new_pan_offset = (var->yoffset * info->fix.line_length) +
+	new_pan_offset = (var->yoffset * info->fix.line_length) +
 		(var->xoffset * (info->var.bits_per_pixel / 8));
 
-	if (ch->new_pan_offset != ch->pan_offset) {
-		unsigned long ldintr;
-		ldintr = lcdc_read(ch->lcdc, _LDINTR);
-		ldintr |= LDINTR_VEE;
-		lcdc_write(ch->lcdc, _LDINTR, ldintr);
-		sh_mobile_lcdc_deferred_io_touch(info);
-	}
+	if (new_pan_offset == ch->pan_offset)
+		return 0;	/* No change, do nothing */
+
+	ldrcntr = lcdc_read(priv, _LDRCNTR);
+
+	/* Set the source address for the next refresh */
+	lcdc_write_chan_mirror(ch, LDSA1R, ch->dma_handle + new_pan_offset);
+	if (lcdc_chan_is_sublcd(ch))
+		lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_SRS);
+	else
+		lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_MRS);
+
+	ch->pan_offset = new_pan_offset;
+
+	sh_mobile_lcdc_deferred_io_touch(info);
 
 	return 0;
 }
 
+static int sh_mobile_wait_for_vsync(struct fb_info *info)
+{
+	struct sh_mobile_lcdc_chan *ch = info->par;
+	unsigned long ldintr;
+	int ret;
+
+	/* Enable VSync End interrupt */
+	ldintr = lcdc_read(ch->lcdc, _LDINTR);
+	ldintr |= LDINTR_VEE;
+	lcdc_write(ch->lcdc, _LDINTR, ldintr);
+
+	ret = wait_for_completion_interruptible_timeout(&ch->vsync_completion,
+							msecs_to_jiffies(100));
+	if (!ret)
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+static int sh_mobile_ioctl(struct fb_info *info, unsigned int cmd,
+		       unsigned long arg)
+{
+	int retval;
+
+	switch (cmd) {
+	case FBIO_WAITFORVSYNC:
+		retval = sh_mobile_wait_for_vsync(info);
+		break;
+
+	default:
+		retval = -ENOIOCTLCMD;
+		break;
+	}
+	return retval;
+}
+
+
 static struct fb_ops sh_mobile_lcdc_ops = {
 	.owner          = THIS_MODULE,
 	.fb_setcolreg	= sh_mobile_lcdc_setcolreg,
@@ -795,6 +830,7 @@
 	.fb_copyarea	= sh_mobile_lcdc_copyarea,
 	.fb_imageblit	= sh_mobile_lcdc_imageblit,
 	.fb_pan_display = sh_mobile_fb_pan_display,
+	.fb_ioctl       = sh_mobile_ioctl,
 };
 
 static int sh_mobile_lcdc_set_bpp(struct fb_var_screeninfo *var, int bpp)
@@ -962,8 +998,8 @@
 			goto err1;
 		}
 		init_waitqueue_head(&priv->ch[i].frame_end_wait);
+		init_completion(&priv->ch[i].vsync_completion);
 		priv->ch[j].pan_offset = 0;
-		priv->ch[j].new_pan_offset = 0;
 
 		switch (pdata->ch[i].chan) {
 		case LCDC_CHAN_MAINLCD:
diff --git a/include/linux/mtd/sh_flctl.h b/include/linux/mtd/sh_flctl.h
index e77c1ce..ab77609 100644
--- a/include/linux/mtd/sh_flctl.h
+++ b/include/linux/mtd/sh_flctl.h
@@ -51,6 +51,8 @@
 #define _4ECCCNTEN	(0x1 << 24)
 #define _4ECCEN		(0x1 << 23)
 #define _4ECCCORRECT	(0x1 << 22)
+#define SHBUSSEL	(0x1 << 20)
+#define SEL_16BIT	(0x1 << 19)
 #define SNAND_E		(0x1 << 18)	/* SNAND (0=512 1=2048)*/
 #define QTSEL_E		(0x1 << 17)
 #define ENDIAN		(0x1 << 16)	/* 1 = little endian */
@@ -96,6 +98,7 @@
 struct sh_flctl {
 	struct mtd_info		mtd;
 	struct nand_chip	chip;
+	struct platform_device	*pdev;
 	void __iomem		*reg;
 
 	uint8_t	done_buff[2048 + 64];	/* max size 2048 + 64 */
diff --git a/include/linux/sh_intc.h b/include/linux/sh_intc.h
index 4ef246f..51d288d 100644
--- a/include/linux/sh_intc.h
+++ b/include/linux/sh_intc.h
@@ -45,7 +45,7 @@
 #define INTC_SMP(stride, nr)
 #endif
 
-struct intc_desc {
+struct intc_hw_desc {
 	struct intc_vect *vectors;
 	unsigned int nr_vectors;
 	struct intc_group *groups;
@@ -56,29 +56,40 @@
 	unsigned int nr_prio_regs;
 	struct intc_sense_reg *sense_regs;
 	unsigned int nr_sense_regs;
-	char *name;
 	struct intc_mask_reg *ack_regs;
 	unsigned int nr_ack_regs;
 };
 
 #define _INTC_ARRAY(a) a, sizeof(a)/sizeof(*a)
+#define INTC_HW_DESC(vectors, groups, mask_regs,	\
+		     prio_regs,	sense_regs, ack_regs)	\
+{							\
+	_INTC_ARRAY(vectors), _INTC_ARRAY(groups),	\
+	_INTC_ARRAY(mask_regs), _INTC_ARRAY(prio_regs),	\
+	_INTC_ARRAY(sense_regs), _INTC_ARRAY(ack_regs),	\
+}
+
+struct intc_desc {
+	char *name;
+	intc_enum force_enable;
+	intc_enum force_disable;
+	struct intc_hw_desc hw;
+};
+
 #define DECLARE_INTC_DESC(symbol, chipname, vectors, groups,		\
 	mask_regs, prio_regs, sense_regs)				\
 struct intc_desc symbol __initdata = {					\
-	_INTC_ARRAY(vectors), _INTC_ARRAY(groups),			\
-	_INTC_ARRAY(mask_regs), _INTC_ARRAY(prio_regs),			\
-	_INTC_ARRAY(sense_regs),					\
-	chipname,							\
+	.name = chipname,						\
+	.hw = INTC_HW_DESC(vectors, groups, mask_regs,			\
+			   prio_regs, sense_regs, NULL),		\
 }
 
 #define DECLARE_INTC_DESC_ACK(symbol, chipname, vectors, groups,	\
 	mask_regs, prio_regs, sense_regs, ack_regs)			\
 struct intc_desc symbol __initdata = {					\
-	_INTC_ARRAY(vectors), _INTC_ARRAY(groups),			\
-	_INTC_ARRAY(mask_regs), _INTC_ARRAY(prio_regs),			\
-	_INTC_ARRAY(sense_regs),					\
-	chipname,							\
-	_INTC_ARRAY(ack_regs),						\
+	.name = chipname,						\
+	.hw = INTC_HW_DESC(vectors, groups, mask_regs,			\
+			   prio_regs, sense_regs, ack_regs),		\
 }
 
 void __init register_intc_controller(struct intc_desc *desc);
diff --git a/include/video/sh_mobile_lcdc.h b/include/video/sh_mobile_lcdc.h
index 2882054..2cc893f 100644
--- a/include/video/sh_mobile_lcdc.h
+++ b/include/video/sh_mobile_lcdc.h
@@ -34,6 +34,8 @@
 #define LCDC_FLAGS_HSCNT (1 << 3) /* Disable HSYNC during VBLANK */
 #define LCDC_FLAGS_DWCNT (1 << 4) /* Disable dotclock during blanking */
 
+#define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32)
+
 struct sh_mobile_lcdc_sys_bus_cfg {
 	unsigned long ldmt2r;
 	unsigned long ldmt3r;
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 25c3ed5..d62e3cd 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -355,7 +355,7 @@
 config DEBUG_KMEMLEAK
 	bool "Kernel memory leak detector"
 	depends on DEBUG_KERNEL && EXPERIMENTAL && !MEMORY_HOTPLUG && \
-		(X86 || ARM || PPC || S390)
+		(X86 || ARM || PPC || S390 || SUPERH)
 
 	select DEBUG_FS if SYSFS
 	select STACKTRACE if STACKTRACE_SUPPORT
diff --git a/mm/Kconfig b/mm/Kconfig
index 17b8947..d34c2b9 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -195,7 +195,7 @@
 config NR_QUICK
 	int
 	depends on QUICKLIST
-	default "2" if SUPERH || AVR32
+	default "2" if AVR32
 	default "1"
 
 config VIRT_TO_BUS