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

* master.kernel.org:/pub/scm/linux/kernel/git/lethal/sh-2.6: (26 commits)
  sh: intc - add support for SH7750 and its variants
  sh: Move entry point code to .text.head.
  sh: heartbeat: Shut up resource size warning.
  sh: update r2d defconfig and fix SH7751R pci compliation
  sh: Many symbol exports for nommu allmodconfig.
  sh: zero terminate 8250 platform data for r2d board
  sh: cpufreq: Fix up the build for SH-2.
  sh: Make on-chip DMA channel selection explicit.
  sh: Fix up CPU dependencies for on-chip DMAC.
  sh: cpufreq: clock framework support.
  sh: Support rate rounding for SH7722 FRQCR clocks.
  sh: Implement clk_round_rate() in the clock framework.
  sh: Fix up PCI section mismatch warnings.
  sh: Wire up fallocate() syscall.
  sh: intc - add support for 7780
  sh: intc - improve group support
  sh: Fix up SH-3 and SH-4 driver dependencies.
  sh: push-switch: Correct license string.
  sh: cpufreq: Fix driver dependencies and flag as broken.
  sh: IPR/INTC2 IRQ setup consolidation.
  ...
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index d8ed667..f87f429 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -178,6 +178,9 @@
 config CPU_HAS_MASKREG_IRQ
 	bool
 
+config CPU_HAS_INTC_IRQ
+	bool
+
 config CPU_HAS_INTC2_IRQ
 	bool
 
@@ -209,6 +212,7 @@
 config SH_SOLUTION_ENGINE
 	bool "SolutionEngine"
 	select SOLUTION_ENGINE
+	select CPU_HAS_IPR_IRQ
 	depends on CPU_SUBTYPE_SH7709 || CPU_SUBTYPE_SH7750
 	help
 	  Select SolutionEngine if configuring for a Hitachi SH7709
@@ -241,6 +245,7 @@
 config SH_7751_SOLUTION_ENGINE
 	bool "SolutionEngine7751"
 	select SOLUTION_ENGINE
+	select CPU_HAS_IPR_IRQ
 	depends on CPU_SUBTYPE_SH7751
 	help
 	  Select 7751 SolutionEngine if configuring for a Hitachi SH7751
@@ -250,6 +255,7 @@
 	bool "SolutionEngine7780"
 	select SOLUTION_ENGINE
 	select SYS_SUPPORTS_PCI
+	select CPU_HAS_INTC2_IRQ
 	depends on CPU_SUBTYPE_SH7780
 	help
 	  Select 7780 SolutionEngine if configuring for a Renesas SH7780
@@ -317,6 +323,7 @@
 config SH_SH03
 	bool "Interface CTP/PCI-SH03"
 	depends on CPU_SUBTYPE_SH7751 && BROKEN
+	select CPU_HAS_IPR_IRQ
 	select SYS_SUPPORTS_PCI
 	help
 	  CTP/PCI-SH03 is a CPU module computer that is produced
@@ -326,6 +333,7 @@
 config SH_SECUREEDGE5410
 	bool "SecureEdge5410"
 	depends on CPU_SUBTYPE_SH7751R
+	select CPU_HAS_IPR_IRQ
 	select SYS_SUPPORTS_PCI
 	help
 	  Select SecureEdge5410 if configuring for a SnapGear SH board.
@@ -380,6 +388,7 @@
 config SH_TITAN
 	bool "TITAN"
 	depends on CPU_SUBTYPE_SH7751R
+	select CPU_HAS_IPR_IRQ
 	select SYS_SUPPORTS_PCI
 	help
 	  Select Titan if you are configuring for a Nimble Microsystems
@@ -388,6 +397,7 @@
 config SH_SHMIN
 	bool "SHMIN"
 	depends on CPU_SUBTYPE_SH7706
+	select CPU_HAS_IPR_IRQ
 	help
 	  Select SHMIN if configuring for the SHMIN board.
 
diff --git a/arch/sh/Makefile b/arch/sh/Makefile
index 77fecc6..0016609 100644
--- a/arch/sh/Makefile
+++ b/arch/sh/Makefile
@@ -121,8 +121,7 @@
 endif
 
 # Companion chips
-core-$(CONFIG_HD64461)		+= arch/sh/cchips/hd6446x/hd64461/
-core-$(CONFIG_HD64465)		+= arch/sh/cchips/hd6446x/hd64465/
+core-$(CONFIG_HD6446X_SERIES)	+= arch/sh/cchips/hd6446x/
 core-$(CONFIG_VOYAGERGX)	+= arch/sh/cchips/voyagergx/
 
 cpuincdir-$(CONFIG_CPU_SH2)	:= cpu-sh2
diff --git a/arch/sh/boards/mpc1211/pci.c b/arch/sh/boards/mpc1211/pci.c
index 4ed1a95..23849f7 100644
--- a/arch/sh/boards/mpc1211/pci.c
+++ b/arch/sh/boards/mpc1211/pci.c
@@ -187,7 +187,7 @@
  *  are examined.
  */
 
-void __init pcibios_fixup_bus(struct pci_bus *b)
+void __devinit pcibios_fixup_bus(struct pci_bus *b)
 {
 	pci_read_bridge_bases(b);
 }
diff --git a/arch/sh/boards/renesas/r7780rp/setup.c b/arch/sh/boards/renesas/r7780rp/setup.c
index 5afb864..adb529d 100644
--- a/arch/sh/boards/renesas/r7780rp/setup.c
+++ b/arch/sh/boards/renesas/r7780rp/setup.c
@@ -21,6 +21,58 @@
 #include <asm/clock.h>
 #include <asm/io.h>
 
+static struct resource r8a66597_usb_host_resources[] = {
+	[0] = {
+		.name	= "r8a66597_hcd",
+		.start	= 0xA4200000,
+		.end	= 0xA42000FF,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.name	= "r8a66597_hcd",
+		.start	= 11,		/* irq number */
+		.end	= 11,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device r8a66597_usb_host_device = {
+	.name		= "r8a66597_hcd",
+	.id		= -1,
+	.dev = {
+		.dma_mask		= NULL,		/* don't use dma */
+		.coherent_dma_mask	= 0xffffffff,
+	},
+	.num_resources	= ARRAY_SIZE(r8a66597_usb_host_resources),
+	.resource	= r8a66597_usb_host_resources,
+};
+
+static struct resource m66592_usb_peripheral_resources[] = {
+	[0] = {
+		.name	= "m66592_udc",
+		.start	= 0xb0000000,
+		.end	= 0xb00000FF,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.name	= "m66592_udc",
+		.start	= 9,		/* irq number */
+		.end	= 9,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device m66592_usb_peripheral_device = {
+	.name		= "m66592_udc",
+	.id		= -1,
+	.dev = {
+		.dma_mask		= NULL,		/* don't use dma */
+		.coherent_dma_mask	= 0xffffffff,
+	},
+	.num_resources	= ARRAY_SIZE(m66592_usb_peripheral_resources),
+	.resource	= m66592_usb_peripheral_resources,
+};
+
 static struct resource cf_ide_resources[] = {
 	[0] = {
 		.start	= PA_AREA5_IO + 0x1000,
@@ -81,6 +133,8 @@
 };
 
 static struct platform_device *r7780rp_devices[] __initdata = {
+	&r8a66597_usb_host_device,
+	&m66592_usb_peripheral_device,
 	&cf_ide_device,
 	&heartbeat_device,
 };
diff --git a/arch/sh/boards/renesas/rts7751r2d/setup.c b/arch/sh/boards/renesas/rts7751r2d/setup.c
index 656fda3..e165d85 100644
--- a/arch/sh/boards/renesas/rts7751r2d/setup.c
+++ b/arch/sh/boards/renesas/rts7751r2d/setup.c
@@ -86,7 +86,8 @@
 		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
 		.regshift	= 2,
 		.uartclk	= (9600 * 16),
-	}
+	},
+	{ 0 },
 };
 
 static struct platform_device uart_device = {
diff --git a/arch/sh/boards/se/7722/irq.c b/arch/sh/boards/se/7722/irq.c
index 26cff0e..0b03f3f 100644
--- a/arch/sh/boards/se/7722/irq.c
+++ b/arch/sh/boards/se/7722/irq.c
@@ -16,95 +16,61 @@
 #include <asm/io.h>
 #include <asm/se7722.h>
 
-#define INTC_INTMSK0             0xFFD00044
-#define INTC_INTMSKCLR0          0xFFD00064
-
-struct se7722_data {
-	unsigned char irq;
-	unsigned char ipr_idx;
-	unsigned char shift;
-	unsigned short priority;
-	unsigned long addr;
-};
-
-
 static void disable_se7722_irq(unsigned int irq)
 {
-	struct se7722_data *p = get_irq_chip_data(irq);
-	ctrl_outw( ctrl_inw( p->addr ) | p->priority , p->addr );
+	unsigned int bit = irq - SE7722_FPGA_IRQ_BASE;
+	ctrl_outw(ctrl_inw(IRQ01_MASK) | 1 << bit, IRQ01_MASK);
 }
 
 static void enable_se7722_irq(unsigned int irq)
 {
-	struct se7722_data *p = get_irq_chip_data(irq);
-	ctrl_outw( ctrl_inw( p->addr ) & ~p->priority , p->addr );
+	unsigned int bit = irq - SE7722_FPGA_IRQ_BASE;
+	ctrl_outw(ctrl_inw(IRQ01_MASK) & ~(1 << bit), IRQ01_MASK);
 }
 
 static struct irq_chip se7722_irq_chip __read_mostly = {
-	.name           = "SE7722",
+	.name           = "SE7722-FPGA",
 	.mask           = disable_se7722_irq,
 	.unmask         = enable_se7722_irq,
 	.mask_ack       = disable_se7722_irq,
 };
 
-static struct se7722_data ipr_irq_table[] = {
-	/* irq        ,idx,sft, priority     , addr   */
-	{ MRSHPC_IRQ0 , 0 , 0 , MRSHPC_BIT0 , IRQ01_MASK } ,
-	{ MRSHPC_IRQ1 , 0 , 0 , MRSHPC_BIT1 , IRQ01_MASK } ,
-	{ MRSHPC_IRQ2 , 0 , 0 , MRSHPC_BIT2 , IRQ01_MASK } ,
-	{ MRSHPC_IRQ3 , 0 , 0 , MRSHPC_BIT3 , IRQ01_MASK } ,
-	{ SMC_IRQ     , 0 , 0 , SMC_BIT     , IRQ01_MASK } ,
-	{ EXT_IRQ     , 0 , 0 , EXT_BIT     , IRQ01_MASK } ,
-};
-
-int se7722_irq_demux(int irq)
+static void se7722_irq_demux(unsigned int irq, struct irq_desc *desc)
 {
+	unsigned short intv = ctrl_inw(IRQ01_STS);
+	struct irq_desc *ext_desc;
+	unsigned int ext_irq = SE7722_FPGA_IRQ_BASE;
 
-	if ((irq == IRQ0_IRQ)||(irq == IRQ1_IRQ)) {
-		volatile unsigned short intv =
-			*(volatile unsigned short *)IRQ01_STS;
-		if (irq == IRQ0_IRQ){
-			if(intv & SMC_BIT ) {
-				return SMC_IRQ;
-			} else if(intv & USB_BIT) {
-				return USB_IRQ;
-			} else {
-				printk("intv =%04x\n", intv);
-				return SMC_IRQ;
-			}
-		} else if(irq == IRQ1_IRQ){
-			if(intv & MRSHPC_BIT0) {
-				return MRSHPC_IRQ0;
-			} else if(intv & MRSHPC_BIT1) {
-				return MRSHPC_IRQ1;
-			} else if(intv & MRSHPC_BIT2) {
-				return MRSHPC_IRQ2;
-			} else if(intv & MRSHPC_BIT3) {
-				return MRSHPC_IRQ3;
-			} else {
-				printk("BIT_EXTENTION =%04x\n", intv);
-				return EXT_IRQ;
-			}
+	intv &= (1 << SE7722_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++;
 	}
-	return irq;
-
 }
+
 /*
  * Initialize IRQ setting
  */
 void __init init_se7722_IRQ(void)
 {
-	int i = 0;
-	ctrl_outw(0x2000, 0xb03fffec);  /* mrshpc irq enable */
-	ctrl_outl((3 << ((7 - 0) * 4))|(3 << ((7 - 1) * 4)), INTC_INTPRI0);     /* irq0 pri=3,irq1,pri=3 */
-	ctrl_outw((2 << ((7 - 0) * 2))|(2 << ((7 - 1) * 2)), INTC_ICR1);        /* irq0,1 low-level irq */
+	int i;
 
-	for (i = 0; i < ARRAY_SIZE(ipr_irq_table); i++) {
-		disable_irq_nosync(ipr_irq_table[i].irq);
-		set_irq_chip_and_handler_name( ipr_irq_table[i].irq, &se7722_irq_chip,
-			handle_level_irq, "level");
-		set_irq_chip_data( ipr_irq_table[i].irq, &ipr_irq_table[i] );
-		disable_se7722_irq(ipr_irq_table[i].irq);
-	}
+	ctrl_outw(0, IRQ01_MASK);       /* disable all irqs */
+	ctrl_outw(0x2000, 0xb03fffec);  /* mrshpc irq enable */
+
+	for (i = 0; i < SE7722_FPGA_IRQ_NR; i++)
+		set_irq_chip_and_handler_name(SE7722_FPGA_IRQ_BASE + i,
+					      &se7722_irq_chip,
+					      handle_level_irq, "level");
+
+	set_irq_chained_handler(IRQ0_IRQ, se7722_irq_demux);
+	set_irq_type(IRQ0_IRQ, IRQ_TYPE_LEVEL_LOW);
+
+	set_irq_chained_handler(IRQ1_IRQ, se7722_irq_demux);
+	set_irq_type(IRQ1_IRQ, IRQ_TYPE_LEVEL_LOW);
 }
diff --git a/arch/sh/boards/se/7722/setup.c b/arch/sh/boards/se/7722/setup.c
index 6cca6cb..495fc7e 100644
--- a/arch/sh/boards/se/7722/setup.c
+++ b/arch/sh/boards/se/7722/setup.c
@@ -77,6 +77,7 @@
 	},
 	[2] = {
 		.start  = MRSHPC_IRQ0,
+		.end    = MRSHPC_IRQ0,
 		.flags  = IORESOURCE_IRQ,
 	},
 };
@@ -140,8 +141,6 @@
 static struct sh_machine_vector mv_se7722 __initmv = {
 	.mv_name                = "Solution Engine 7722" ,
 	.mv_setup               = se7722_setup ,
-	.mv_nr_irqs		= 109 ,
+	.mv_nr_irqs		= SE7722_FPGA_IRQ_BASE + SE7722_FPGA_IRQ_NR,
 	.mv_init_irq		= init_se7722_IRQ,
-	.mv_irq_demux           = se7722_irq_demux,
-
 };
diff --git a/arch/sh/cchips/hd6446x/Makefile b/arch/sh/cchips/hd6446x/Makefile
new file mode 100644
index 0000000..a106dd9
--- /dev/null
+++ b/arch/sh/cchips/hd6446x/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_HD64461)	+= hd64461.o
+obj-$(CONFIG_HD64465)	+= hd64465/
diff --git a/arch/sh/cchips/hd6446x/hd64461/setup.c b/arch/sh/cchips/hd6446x/hd64461.c
similarity index 97%
rename from arch/sh/cchips/hd6446x/hd64461/setup.c
rename to arch/sh/cchips/hd6446x/hd64461.c
index 4d49b5c..97f6512 100644
--- a/arch/sh/cchips/hd6446x/hd64461/setup.c
+++ b/arch/sh/cchips/hd6446x/hd64461.c
@@ -1,5 +1,4 @@
 /*
- *	$Id: setup.c,v 1.5 2004/03/16 00:07:50 lethal Exp $
  *	Copyright (C) 2000 YAEGASHI Takeshi
  *	Hitachi HD64461 companion chip support
  */
diff --git a/arch/sh/cchips/hd6446x/hd64461/Makefile b/arch/sh/cchips/hd6446x/hd64461/Makefile
deleted file mode 100644
index bff4b92..0000000
--- a/arch/sh/cchips/hd6446x/hd64461/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-#
-# Makefile for the HD64461 
-#
-
-obj-y	 := setup.o io.o
-
diff --git a/arch/sh/cchips/hd6446x/hd64461/io.c b/arch/sh/cchips/hd6446x/hd64461/io.c
deleted file mode 100644
index 7909a1b..0000000
--- a/arch/sh/cchips/hd6446x/hd64461/io.c
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- *	Copyright (C) 2000 YAEGASHI Takeshi
- *	Typical I/O routines for HD64461 system.
- */
-
-#include <asm/io.h>
-#include <asm/hd64461.h>
-
-#define MEM_BASE (CONFIG_HD64461_IOBASE - HD64461_STBCR)
-
-static __inline__ unsigned long PORT2ADDR(unsigned long port)
-{
-	/* 16550A: HD64461 internal */
-	if (0x3f8<=port && port<=0x3ff)
-		return CONFIG_HD64461_IOBASE + 0x8000 + ((port-0x3f8)<<1);
-	if (0x2f8<=port && port<=0x2ff)
-		return CONFIG_HD64461_IOBASE + 0x7000 + ((port-0x2f8)<<1);
-
-#ifdef CONFIG_HD64461_ENABLER
-	/* NE2000: HD64461 PCMCIA channel 0 (I/O) */
-	if (0x300<=port && port<=0x31f)
-		return 0xba000000 + port;
-
-	/* ide0: HD64461 PCMCIA channel 1 (memory) */
-	/* On HP690, CF in slot 1 is configured as a memory card
-	   device.  See CF+ and CompactFlash Specification for the
-	   detail of CF's memory mapped addressing. */
-	if (0x1f0<=port && port<=0x1f7)	return 0xb5000000 + port;
-	if (port == 0x3f6) return 0xb50001fe;
-	if (port == 0x3f7) return 0xb50001ff;
-
-	/* ide1 */
-	if (0x170<=port && port<=0x177)	return 0xba000000 + port;
-	if (port == 0x376) return 0xba000376;
-	if (port == 0x377) return 0xba000377;
-#endif
-
-	/* ??? */
-	if (port < 0xf000) return 0xa0000000 + port;
-	/* PCMCIA channel 0, I/O (0xba000000) */
-	if (port < 0x10000) return 0xba000000 + port - 0xf000;
-
-	/* HD64461 internal devices (0xb0000000) */
-	if (port < 0x20000) return CONFIG_HD64461_IOBASE + port - 0x10000;
-
-	/* PCMCIA channel 0, I/O (0xba000000) */
-	if (port < 0x30000) return 0xba000000 + port - 0x20000;
-
-	/* PCMCIA channel 1, memory (0xb5000000) */
-	if (port < 0x40000) return 0xb5000000 + port - 0x30000;
-
-	/* Whole physical address space (0xa0000000) */
-	return 0xa0000000 + (port & 0x1fffffff);
-}
-
-unsigned char hd64461_inb(unsigned long port)
-{
-	return *(volatile unsigned char*)PORT2ADDR(port);
-}
-
-unsigned char hd64461_inb_p(unsigned long port)
-{
-	unsigned long v = *(volatile unsigned char*)PORT2ADDR(port);
-	ctrl_delay();
-	return v;
-}
-
-unsigned short hd64461_inw(unsigned long port)
-{
-	return *(volatile unsigned short*)PORT2ADDR(port);
-}
-
-unsigned int hd64461_inl(unsigned long port)
-{
-	return *(volatile unsigned long*)PORT2ADDR(port);
-}
-
-void hd64461_outb(unsigned char b, unsigned long port)
-{
-	*(volatile unsigned char*)PORT2ADDR(port) = b;
-}
-
-void hd64461_outb_p(unsigned char b, unsigned long port)
-{
-	*(volatile unsigned char*)PORT2ADDR(port) = b;
-	ctrl_delay();
-}
-
-void hd64461_outw(unsigned short b, unsigned long port)
-{
-	*(volatile unsigned short*)PORT2ADDR(port) = b;
-}
-
-void hd64461_outl(unsigned int b, unsigned long port)
-{
-        *(volatile unsigned long*)PORT2ADDR(port) = b;
-}
-
-void hd64461_insb(unsigned long port, void *buffer, unsigned long count)
-{
-	volatile unsigned char* addr=(volatile unsigned char*)PORT2ADDR(port);
-	unsigned char *buf=buffer;
-	while(count--) *buf++=*addr;
-}
-
-void hd64461_insw(unsigned long port, void *buffer, unsigned long count)
-{
-	volatile unsigned short* addr=(volatile unsigned short*)PORT2ADDR(port);
-	unsigned short *buf=buffer;
-	while(count--) *buf++=*addr;
-}
-
-void hd64461_insl(unsigned long port, void *buffer, unsigned long count)
-{
-	volatile unsigned long* addr=(volatile unsigned long*)PORT2ADDR(port);
-	unsigned long *buf=buffer;
-	while(count--) *buf++=*addr;
-}
-
-void hd64461_outsb(unsigned long port, const void *buffer, unsigned long count)
-{
-	volatile unsigned char* addr=(volatile unsigned char*)PORT2ADDR(port);
-	const unsigned char *buf=buffer;
-	while(count--) *addr=*buf++;
-}
-
-void hd64461_outsw(unsigned long port, const void *buffer, unsigned long count)
-{
-	volatile unsigned short* addr=(volatile unsigned short*)PORT2ADDR(port);
-	const unsigned short *buf=buffer;
-	while(count--) *addr=*buf++;
-}
-
-void hd64461_outsl(unsigned long port, const void *buffer, unsigned long count)
-{
-	volatile unsigned long* addr=(volatile unsigned long*)PORT2ADDR(port);
-	const unsigned long *buf=buffer;
-	while(count--) *addr=*buf++;
-}
-
-unsigned short hd64461_readw(void __iomem *addr)
-{
-	return ctrl_inw(MEM_BASE+(unsigned long __force)addr);
-}
-
-void hd64461_writew(unsigned short b, void __iomem *addr)
-{
-	ctrl_outw(b, MEM_BASE+(unsigned long __force)addr);
-}
-
diff --git a/arch/sh/configs/landisk_defconfig b/arch/sh/configs/landisk_defconfig
index e7f8ddb..07310fa 100644
--- a/arch/sh/configs/landisk_defconfig
+++ b/arch/sh/configs/landisk_defconfig
@@ -217,7 +217,7 @@
 # CONFIG_SH_DSP is not set
 # CONFIG_SH_STORE_QUEUES is not set
 CONFIG_CPU_HAS_INTEVT=y
-CONFIG_CPU_HAS_IPR_IRQ=y
+CONFIG_CPU_HAS_INTC_IRQ=y
 CONFIG_CPU_HAS_SR_RB=y
 CONFIG_CPU_HAS_PTEA=y
 
diff --git a/arch/sh/configs/lboxre2_defconfig b/arch/sh/configs/lboxre2_defconfig
index be86414..fa09d68 100644
--- a/arch/sh/configs/lboxre2_defconfig
+++ b/arch/sh/configs/lboxre2_defconfig
@@ -222,7 +222,7 @@
 # CONFIG_SH_DSP is not set
 # CONFIG_SH_STORE_QUEUES is not set
 CONFIG_CPU_HAS_INTEVT=y
-CONFIG_CPU_HAS_IPR_IRQ=y
+CONFIG_CPU_HAS_INTC_IRQ=y
 CONFIG_CPU_HAS_SR_RB=y
 CONFIG_CPU_HAS_PTEA=y
 
diff --git a/arch/sh/configs/r7780mp_defconfig b/arch/sh/configs/r7780mp_defconfig
index 17f7402..ac4de49 100644
--- a/arch/sh/configs/r7780mp_defconfig
+++ b/arch/sh/configs/r7780mp_defconfig
@@ -191,7 +191,7 @@
 CONFIG_SH_STORE_QUEUES=y
 CONFIG_SPECULATIVE_EXECUTION=y
 CONFIG_CPU_HAS_INTEVT=y
-CONFIG_CPU_HAS_INTC2_IRQ=y
+CONFIG_CPU_HAS_INTC_IRQ=y
 CONFIG_CPU_HAS_SR_RB=y
 
 #
diff --git a/arch/sh/configs/r7780rp_defconfig b/arch/sh/configs/r7780rp_defconfig
index 48c6a21..12cc0191 100644
--- a/arch/sh/configs/r7780rp_defconfig
+++ b/arch/sh/configs/r7780rp_defconfig
@@ -241,7 +241,7 @@
 CONFIG_SH_STORE_QUEUES=y
 CONFIG_SPECULATIVE_EXECUTION=y
 CONFIG_CPU_HAS_INTEVT=y
-CONFIG_CPU_HAS_INTC2_IRQ=y
+CONFIG_CPU_HAS_INTC_IRQ=y
 CONFIG_CPU_HAS_SR_RB=y
 
 #
diff --git a/arch/sh/configs/rts7751r2d_defconfig b/arch/sh/configs/rts7751r2d_defconfig
index a59bb78..f1e979b 100644
--- a/arch/sh/configs/rts7751r2d_defconfig
+++ b/arch/sh/configs/rts7751r2d_defconfig
@@ -155,7 +155,7 @@
 # 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=y
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
 CONFIG_CPU_SUBTYPE_SH7751R=y
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
@@ -218,7 +218,7 @@
 # CONFIG_SH_DSP is not set
 # CONFIG_SH_STORE_QUEUES is not set
 CONFIG_CPU_HAS_INTEVT=y
-CONFIG_CPU_HAS_IPR_IRQ=y
+CONFIG_CPU_HAS_INTC_IRQ=y
 CONFIG_CPU_HAS_SR_RB=y
 CONFIG_CPU_HAS_PTEA=y
 
@@ -280,7 +280,7 @@
 CONFIG_BOOT_LINK_OFFSET=0x00800000
 # CONFIG_UBC_WAKEUP is not set
 CONFIG_CMDLINE_BOOL=y
-CONFIG_CMDLINE="console=tty0 console=ttySC0,115200 root=/dev/sda1"
+CONFIG_CMDLINE="console=tty0 console=ttySC0,115200 root=/dev/sda1 earlyprintk=bios"
 
 #
 # Bus options
@@ -1323,7 +1323,7 @@
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_BUGVERBOSE is not set
-# CONFIG_SH_STANDARD_BIOS is not set
+CONFIG_SH_STANDARD_BIOS=y
 CONFIG_EARLY_SCIF_CONSOLE=y
 CONFIG_EARLY_SCIF_CONSOLE_PORT=0xffe80000
 CONFIG_EARLY_PRINTK=y
diff --git a/arch/sh/configs/se7722_defconfig b/arch/sh/configs/se7722_defconfig
index 764b813..8e6a6ba 100644
--- a/arch/sh/configs/se7722_defconfig
+++ b/arch/sh/configs/se7722_defconfig
@@ -200,7 +200,7 @@
 CONFIG_SH_DSP=y
 CONFIG_SH_STORE_QUEUES=y
 CONFIG_CPU_HAS_INTEVT=y
-CONFIG_CPU_HAS_IPR_IRQ=y
+CONFIG_CPU_HAS_INTC_IRQ=y
 CONFIG_CPU_HAS_SR_RB=y
 CONFIG_CPU_HAS_PTEA=y
 
@@ -565,7 +565,7 @@
 # Non-8250 serial port support
 #
 CONFIG_SERIAL_SH_SCI=y
-CONFIG_SERIAL_SH_SCI_NR_UARTS=2
+CONFIG_SERIAL_SH_SCI_NR_UARTS=3
 CONFIG_SERIAL_SH_SCI_CONSOLE=y
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
diff --git a/arch/sh/configs/se7750_defconfig b/arch/sh/configs/se7750_defconfig
index 4e6e77f..c60b6fd 100644
--- a/arch/sh/configs/se7750_defconfig
+++ b/arch/sh/configs/se7750_defconfig
@@ -226,7 +226,7 @@
 # CONFIG_SH_DSP is not set
 # CONFIG_SH_STORE_QUEUES is not set
 CONFIG_CPU_HAS_INTEVT=y
-CONFIG_CPU_HAS_IPR_IRQ=y
+CONFIG_CPU_HAS_INTC_IRQ=y
 CONFIG_CPU_HAS_SR_RB=y
 CONFIG_CPU_HAS_PTEA=y
 
diff --git a/arch/sh/configs/se7780_defconfig b/arch/sh/configs/se7780_defconfig
index 538661e..f68743d 100644
--- a/arch/sh/configs/se7780_defconfig
+++ b/arch/sh/configs/se7780_defconfig
@@ -218,6 +218,7 @@
 # CONFIG_SH_STORE_QUEUES is not set
 CONFIG_CPU_HAS_INTEVT=y
 CONFIG_CPU_HAS_INTC2_IRQ=y
+CONFIG_CPU_HAS_INTC_IRQ=y
 CONFIG_CPU_HAS_SR_RB=y
 
 #
diff --git a/arch/sh/drivers/dma/Kconfig b/arch/sh/drivers/dma/Kconfig
index 3338980..ee71143 100644
--- a/arch/sh/drivers/dma/Kconfig
+++ b/arch/sh/drivers/dma/Kconfig
@@ -5,12 +5,13 @@
 
 config SH_DMA
 	bool "SuperH on-chip DMA controller (DMAC) support"
+	depends on CPU_SH3 || CPU_SH4
 	select SH_DMA_API
 	default n
 
 config NR_ONCHIP_DMA_CHANNELS
+	int
 	depends on SH_DMA
-	int "Number of on-chip DMAC channels"
 	default "8" if CPU_SUBTYPE_SH7750R || CPU_SUBTYPE_SH7751R
 	default "12" if CPU_SUBTYPE_SH7780
 	default "4"
diff --git a/arch/sh/drivers/heartbeat.c b/arch/sh/drivers/heartbeat.c
index 23dd608..10c1828 100644
--- a/arch/sh/drivers/heartbeat.c
+++ b/arch/sh/drivers/heartbeat.c
@@ -78,7 +78,7 @@
 			hd->bit_pos[i] = i;
 	}
 
-	hd->base = (void __iomem *)res->start;
+	hd->base = (void __iomem *)(unsigned long)res->start;
 
 	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 0e9b532..2f65ac7 100644
--- a/arch/sh/drivers/pci/Makefile
+++ b/arch/sh/drivers/pci/Makefile
@@ -7,6 +7,7 @@
 
 obj-$(CONFIG_CPU_SUBTYPE_ST40STB1)	+= pci-st40.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_SH7780)	+= pci-sh7780.o ops-sh4.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7785)	+= pci-sh7780.o ops-sh4.o
 
diff --git a/arch/sh/drivers/pci/ops-sh4.c b/arch/sh/drivers/pci/ops-sh4.c
index 54232f1..710a3b0 100644
--- a/arch/sh/drivers/pci/ops-sh4.c
+++ b/arch/sh/drivers/pci/ops-sh4.c
@@ -153,7 +153,7 @@
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
 
-char * __init pcibios_setup(char *str)
+char * __devinit pcibios_setup(char *str)
 {
 	if (!strcmp(str, "off")) {
 		pci_probe = 0;
diff --git a/arch/sh/drivers/pci/pci-st40.c b/arch/sh/drivers/pci/pci-st40.c
index 543417f..1502a14 100644
--- a/arch/sh/drivers/pci/pci-st40.c
+++ b/arch/sh/drivers/pci/pci-st40.c
@@ -328,7 +328,7 @@
 	return 1;
 }
 
-char * __init pcibios_setup(char *str)
+char * __devinit pcibios_setup(char *str)
 {
 	return str;
 }
diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c
index d439336..ccaba36 100644
--- a/arch/sh/drivers/pci/pci.c
+++ b/arch/sh/drivers/pci/pci.c
@@ -71,7 +71,7 @@
  *  Called after each bus is probed, but before its children
  *  are examined.
  */
-void __init pcibios_fixup_bus(struct pci_bus *bus)
+void __devinit pcibios_fixup_bus(struct pci_bus *bus)
 {
 	pci_read_bridge_bases(bus);
 }
diff --git a/arch/sh/drivers/push-switch.c b/arch/sh/drivers/push-switch.c
index b3d20c0..725be6d 100644
--- a/arch/sh/drivers/push-switch.c
+++ b/arch/sh/drivers/push-switch.c
@@ -138,4 +138,4 @@
 
 MODULE_VERSION(DRV_VERSION);
 MODULE_AUTHOR("Paul Mundt");
-MODULE_LICENSE("GPLv2");
+MODULE_LICENSE("GPL v2");
diff --git a/arch/sh/kernel/cpu/clock.c b/arch/sh/kernel/cpu/clock.c
index 6325154..92807ffa 100644
--- a/arch/sh/kernel/cpu/clock.c
+++ b/arch/sh/kernel/cpu/clock.c
@@ -229,6 +229,22 @@
 }
 EXPORT_SYMBOL_GPL(clk_recalc_rate);
 
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	if (likely(clk->ops && clk->ops->round_rate)) {
+		unsigned long flags, rounded;
+
+		spin_lock_irqsave(&clock_lock, flags);
+		rounded = clk->ops->round_rate(clk, rate);
+		spin_unlock_irqrestore(&clock_lock, flags);
+
+		return rounded;
+	}
+
+	return clk_get_rate(clk);
+}
+EXPORT_SYMBOL_GPL(clk_round_rate);
+
 /*
  * Returns a clock. Note that we first try to use device id on the bus
  * and clock name. If this fails, we try to use clock name only.
diff --git a/arch/sh/kernel/cpu/irq/Makefile b/arch/sh/kernel/cpu/irq/Makefile
index 1c23308..9ddb446 100644
--- a/arch/sh/kernel/cpu/irq/Makefile
+++ b/arch/sh/kernel/cpu/irq/Makefile
@@ -6,4 +6,5 @@
 obj-$(CONFIG_CPU_HAS_IPR_IRQ)		+= ipr.o
 obj-$(CONFIG_CPU_HAS_PINT_IRQ)		+= pint.o 
 obj-$(CONFIG_CPU_HAS_MASKREG_IRQ)	+= maskreg.o
+obj-$(CONFIG_CPU_HAS_INTC_IRQ)		+= intc.o
 obj-$(CONFIG_CPU_HAS_INTC2_IRQ)		+= intc2.o
diff --git a/arch/sh/kernel/cpu/irq/intc.c b/arch/sh/kernel/cpu/irq/intc.c
new file mode 100644
index 0000000..9345a71
--- /dev/null
+++ b/arch/sh/kernel/cpu/irq/intc.c
@@ -0,0 +1,405 @@
+/*
+ * Shared interrupt handling code for IPR and INTC2 types of IRQs.
+ *
+ * Copyright (C) 2007 Magnus Damm
+ *
+ * Based on intc2.c and ipr.c
+ *
+ * Copyright (C) 1999  Niibe Yutaka & Takeshi Yaegashi
+ * Copyright (C) 2000  Kazumoto Kojima
+ * Copyright (C) 2001  David J. Mckay (david.mckay@st.com)
+ * Copyright (C) 2003  Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp>
+ * Copyright (C) 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.
+ */
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+
+#define _INTC_MK(fn, idx, bit, value) \
+	((fn) << 24 | ((value) << 16) | ((idx) << 8) | (bit))
+#define _INTC_FN(h) (h >> 24)
+#define _INTC_VALUE(h) ((h >> 16) & 0xff)
+#define _INTC_IDX(h) ((h >> 8) & 0xff)
+#define _INTC_BIT(h) (h & 0xff)
+
+#define _INTC_PTR(desc, member, data) \
+	(desc->member + _INTC_IDX(data))
+
+static inline struct intc_desc *get_intc_desc(unsigned int irq)
+{
+	struct irq_chip *chip = get_irq_chip(irq);
+	return (void *)((char *)chip - offsetof(struct intc_desc, chip));
+}
+
+static inline unsigned int set_field(unsigned int value,
+				     unsigned int field_value,
+				     unsigned int width,
+				     unsigned int shift)
+{
+	value &= ~(((1 << width) - 1) << shift);
+	value |= field_value << shift;
+	return value;
+}
+
+static inline unsigned int set_prio_field(struct intc_desc *desc,
+					  unsigned int value,
+					  unsigned int priority,
+					  unsigned int data)
+{
+	unsigned int width = _INTC_PTR(desc, prio_regs, data)->field_width;
+
+	return set_field(value, priority, width, _INTC_BIT(data));
+}
+
+static void disable_prio_16(struct intc_desc *desc, unsigned int data)
+{
+	unsigned long addr = _INTC_PTR(desc, prio_regs, data)->reg;
+
+	ctrl_outw(set_prio_field(desc, ctrl_inw(addr), 0, data), addr);
+}
+
+static void enable_prio_16(struct intc_desc *desc, unsigned int data)
+{
+	unsigned long addr = _INTC_PTR(desc, prio_regs, data)->reg;
+	unsigned int prio = _INTC_VALUE(data);
+
+	ctrl_outw(set_prio_field(desc, ctrl_inw(addr), prio, data), addr);
+}
+
+static void disable_prio_32(struct intc_desc *desc, unsigned int data)
+{
+	unsigned long addr = _INTC_PTR(desc, prio_regs, data)->reg;
+
+	ctrl_outl(set_prio_field(desc, ctrl_inl(addr), 0, data), addr);
+}
+
+static void enable_prio_32(struct intc_desc *desc, unsigned int data)
+{
+	unsigned long addr = _INTC_PTR(desc, prio_regs, data)->reg;
+	unsigned int prio = _INTC_VALUE(data);
+
+	ctrl_outl(set_prio_field(desc, ctrl_inl(addr), prio, data), addr);
+}
+
+static void disable_mask_8(struct intc_desc *desc, unsigned int data)
+{
+	ctrl_outb(1 << _INTC_BIT(data),
+		  _INTC_PTR(desc, mask_regs, data)->set_reg);
+}
+
+static void enable_mask_8(struct intc_desc *desc, unsigned int data)
+{
+	ctrl_outb(1 << _INTC_BIT(data),
+		  _INTC_PTR(desc, mask_regs, data)->clr_reg);
+}
+
+static void disable_mask_32(struct intc_desc *desc, unsigned int data)
+{
+	ctrl_outl(1 << _INTC_BIT(data),
+		  _INTC_PTR(desc, mask_regs, data)->set_reg);
+}
+
+static void enable_mask_32(struct intc_desc *desc, unsigned int data)
+{
+	ctrl_outl(1 << _INTC_BIT(data),
+		  _INTC_PTR(desc, mask_regs, data)->clr_reg);
+}
+
+enum {	REG_FN_ERROR=0,
+	REG_FN_MASK_8, REG_FN_MASK_32,
+	REG_FN_PRIO_16, REG_FN_PRIO_32 };
+
+static struct {
+	void (*enable)(struct intc_desc *, unsigned int);
+	void (*disable)(struct intc_desc *, unsigned int);
+} intc_reg_fns[] = {
+	[REG_FN_MASK_8] = { enable_mask_8, disable_mask_8 },
+	[REG_FN_MASK_32] = { enable_mask_32, disable_mask_32 },
+	[REG_FN_PRIO_16] = { enable_prio_16, disable_prio_16 },
+	[REG_FN_PRIO_32] = { enable_prio_32, disable_prio_32 },
+};
+
+static void intc_enable(unsigned int irq)
+{
+	struct intc_desc *desc = get_intc_desc(irq);
+	unsigned int data = (unsigned int) get_irq_chip_data(irq);
+
+	intc_reg_fns[_INTC_FN(data)].enable(desc, data);
+}
+
+static void intc_disable(unsigned int irq)
+{
+	struct intc_desc *desc = get_intc_desc(irq);
+	unsigned int data = (unsigned int) get_irq_chip_data(irq);
+
+	intc_reg_fns[_INTC_FN(data)].disable(desc, data);
+}
+
+static void set_sense_16(struct intc_desc *desc, unsigned int data)
+{
+	unsigned long addr = _INTC_PTR(desc, sense_regs, data)->reg;
+	unsigned int width = _INTC_PTR(desc, sense_regs, data)->field_width;
+	unsigned int bit = _INTC_BIT(data);
+	unsigned int value = _INTC_VALUE(data);
+
+	ctrl_outw(set_field(ctrl_inw(addr), value, width, bit), addr);
+}
+
+static void set_sense_32(struct intc_desc *desc, unsigned int data)
+{
+	unsigned long addr = _INTC_PTR(desc, sense_regs, data)->reg;
+	unsigned int width = _INTC_PTR(desc, sense_regs, data)->field_width;
+	unsigned int bit = _INTC_BIT(data);
+	unsigned int value = _INTC_VALUE(data);
+
+	ctrl_outl(set_field(ctrl_inl(addr), value, width, bit), addr);
+}
+
+#define VALID(x) (x | 0x80)
+
+static unsigned char intc_irq_sense_table[IRQ_TYPE_SENSE_MASK + 1] = {
+	[IRQ_TYPE_EDGE_FALLING] = VALID(0),
+	[IRQ_TYPE_EDGE_RISING] = VALID(1),
+	[IRQ_TYPE_LEVEL_LOW] = VALID(2),
+	[IRQ_TYPE_LEVEL_HIGH] = VALID(3),
+};
+
+static int intc_set_sense(unsigned int irq, unsigned int type)
+{
+	struct intc_desc *desc = get_intc_desc(irq);
+	unsigned char value = intc_irq_sense_table[type & IRQ_TYPE_SENSE_MASK];
+	unsigned int i, j, data, bit;
+	intc_enum enum_id = 0;
+
+	for (i = 0; i < desc->nr_vectors; i++) {
+		struct intc_vect *vect = desc->vectors + i;
+
+		if (evt2irq(vect->vect) != irq)
+			continue;
+
+		enum_id = vect->enum_id;
+		break;
+	}
+
+	if (!enum_id || !value)
+		return -EINVAL;
+
+	value ^= VALID(0);
+
+	for (i = 0; i < desc->nr_sense_regs; i++) {
+		struct intc_sense_reg *sr = desc->sense_regs + i;
+
+		for (j = 0; j < ARRAY_SIZE(sr->enum_ids); j++) {
+			if (sr->enum_ids[j] != enum_id)
+				continue;
+
+			bit = sr->reg_width - ((j + 1) * sr->field_width);
+			data = _INTC_MK(0, i, bit, value);
+
+			switch(sr->reg_width) {
+			case 16:
+				set_sense_16(desc, data);
+				break;
+			case 32:
+				set_sense_32(desc, data);
+				break;
+			}
+
+			return 0;
+		}
+	}
+
+	return -EINVAL;
+}
+
+static unsigned int __init intc_find_mask_handler(unsigned int width)
+{
+	switch (width) {
+	case 8:
+		return REG_FN_MASK_8;
+	case 32:
+		return REG_FN_MASK_32;
+	}
+
+	BUG();
+	return REG_FN_ERROR;
+}
+
+static unsigned int __init intc_find_prio_handler(unsigned int width)
+{
+	switch (width) {
+	case 16:
+		return REG_FN_PRIO_16;
+	case 32:
+		return REG_FN_PRIO_32;
+	}
+
+	BUG();
+	return REG_FN_ERROR;
+}
+
+static intc_enum __init intc_grp_id(struct intc_desc *desc, intc_enum enum_id)
+{
+	struct intc_group *g = desc->groups;
+	unsigned int i, j;
+
+	for (i = 0; g && enum_id && i < desc->nr_groups; i++) {
+		g = desc->groups + i;
+
+		for (j = 0; g->enum_ids[j]; j++) {
+			if (g->enum_ids[j] != enum_id)
+				continue;
+
+			return g->enum_id;
+		}
+	}
+
+	return 0;
+}
+
+static unsigned int __init intc_prio_value(struct intc_desc *desc,
+					   intc_enum enum_id, int do_grps)
+{
+	struct intc_prio *p = desc->priorities;
+	unsigned int i;
+
+	for (i = 0; p && enum_id && i < desc->nr_priorities; i++) {
+		p = desc->priorities + i;
+
+		if (p->enum_id != enum_id)
+			continue;
+
+		return p->priority;
+	}
+
+	if (do_grps)
+		return intc_prio_value(desc, intc_grp_id(desc, enum_id), 0);
+
+	/* default to the lowest priority possible if no priority is set
+	 * - this needs to be at least 2 for 5-bit priorities on 7780
+	 */
+
+	return 2;
+}
+
+static unsigned int __init intc_mask_data(struct intc_desc *desc,
+					  intc_enum enum_id, int do_grps)
+{
+	struct intc_mask_reg *mr = desc->mask_regs;
+	unsigned int i, j, fn;
+
+	for (i = 0; mr && enum_id && i < desc->nr_mask_regs; i++) {
+		mr = desc->mask_regs + i;
+
+		for (j = 0; j < ARRAY_SIZE(mr->enum_ids); j++) {
+			if (mr->enum_ids[j] != enum_id)
+				continue;
+
+			fn = intc_find_mask_handler(mr->reg_width);
+			if (fn == REG_FN_ERROR)
+				return 0;
+
+			return _INTC_MK(fn, i, (mr->reg_width - 1) - j, 0);
+		}
+	}
+
+	if (do_grps)
+		return intc_mask_data(desc, intc_grp_id(desc, enum_id), 0);
+
+	return 0;
+}
+
+static unsigned int __init intc_prio_data(struct intc_desc *desc,
+					  intc_enum enum_id, int do_grps)
+{
+	struct intc_prio_reg *pr = desc->prio_regs;
+	unsigned int i, j, fn, bit, prio;
+
+	for (i = 0; pr && enum_id && i < desc->nr_prio_regs; i++) {
+		pr = desc->prio_regs + i;
+
+		for (j = 0; j < ARRAY_SIZE(pr->enum_ids); j++) {
+			if (pr->enum_ids[j] != enum_id)
+				continue;
+
+			fn = intc_find_prio_handler(pr->reg_width);
+			if (fn == REG_FN_ERROR)
+				return 0;
+
+			prio = intc_prio_value(desc, enum_id, 1);
+			bit = pr->reg_width - ((j + 1) * pr->field_width);
+
+			BUG_ON(bit < 0);
+
+			return _INTC_MK(fn, i, bit, prio);
+		}
+	}
+
+	if (do_grps)
+		return intc_prio_data(desc, intc_grp_id(desc, enum_id), 0);
+
+	return 0;
+}
+
+static void __init intc_register_irq(struct intc_desc *desc, intc_enum enum_id,
+				     unsigned int irq)
+{
+	unsigned int data[2], primary;
+
+	/* Prefer single interrupt source bitmap over other combinations:
+	 * 1. bitmap, single interrupt source
+	 * 2. priority, single interrupt source
+	 * 3. bitmap, multiple interrupt sources (groups)
+	 * 4. priority, multiple interrupt sources (groups)
+	 */
+
+	data[0] = intc_mask_data(desc, enum_id, 0);
+	data[1] = intc_prio_data(desc, enum_id, 0);
+
+	primary = 0;
+	if (!data[0] && data[1])
+		primary = 1;
+
+	data[0] = data[0] ? data[0] : intc_mask_data(desc, enum_id, 1);
+	data[1] = data[1] ? data[1] : intc_prio_data(desc, enum_id, 1);
+
+	if (!data[primary])
+		primary ^= 1;
+
+	BUG_ON(!data[primary]); /* must have primary masking method */
+
+	disable_irq_nosync(irq);
+	set_irq_chip_and_handler_name(irq, &desc->chip,
+				      handle_level_irq, "level");
+	set_irq_chip_data(irq, (void *)data[primary]);
+
+	/* enable secondary masking method if present */
+	if (data[!primary])
+		intc_reg_fns[_INTC_FN(data[!primary])].enable(desc,
+							      data[!primary]);
+
+	/* irq should be disabled by default */
+	desc->chip.mask(irq);
+}
+
+void __init register_intc_controller(struct intc_desc *desc)
+{
+	unsigned int i;
+
+	desc->chip.mask = intc_disable;
+	desc->chip.unmask = intc_enable;
+	desc->chip.mask_ack = intc_disable;
+	desc->chip.set_type = intc_set_sense;
+
+	for (i = 0; i < desc->nr_vectors; i++) {
+		struct intc_vect *vect = desc->vectors + i;
+
+		intc_register_irq(desc, vect->enum_id, evt2irq(vect->vect));
+	}
+}
diff --git a/arch/sh/kernel/cpu/sh2/setup-sh7619.c b/arch/sh/kernel/cpu/sh2/setup-sh7619.c
index 1a107fe..a979b98 100644
--- a/arch/sh/kernel/cpu/sh2/setup-sh7619.c
+++ b/arch/sh/kernel/cpu/sh2/setup-sh7619.c
@@ -88,7 +88,7 @@
 	},
 };
 
-void __init init_IRQ_ipr(void)
+void __init plat_irq_setup(void)
 {
 	register_ipr_controller(&ipr_irq_desc);
 }
diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
index b6e3a63..deab165 100644
--- a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
+++ b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
@@ -107,7 +107,7 @@
 	},
 };
 
-void __init init_IRQ_ipr(void)
+void __init plat_irq_setup(void)
 {
 	register_ipr_controller(&ipr_irq_desc);
 }
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7705.c b/arch/sh/kernel/cpu/sh3/setup-sh7705.c
index a55b8ce..ebd9d06 100644
--- a/arch/sh/kernel/cpu/sh3/setup-sh7705.c
+++ b/arch/sh/kernel/cpu/sh3/setup-sh7705.c
@@ -92,7 +92,7 @@
 	},
 };
 
-void __init init_IRQ_ipr(void)
+void __init plat_irq_setup(void)
 {
 	register_ipr_controller(&ipr_irq_desc);
 }
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7709.c b/arch/sh/kernel/cpu/sh3/setup-sh7709.c
index d79ec0c..086f8e2 100644
--- a/arch/sh/kernel/cpu/sh3/setup-sh7709.c
+++ b/arch/sh/kernel/cpu/sh3/setup-sh7709.c
@@ -139,7 +139,7 @@
 	},
 };
 
-void __init init_IRQ_ipr(void)
+void __init plat_irq_setup(void)
 {
 	register_ipr_controller(&ipr_irq_desc);
 }
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7710.c b/arch/sh/kernel/cpu/sh3/setup-sh7710.c
index f40e6da..1322848 100644
--- a/arch/sh/kernel/cpu/sh3/setup-sh7710.c
+++ b/arch/sh/kernel/cpu/sh3/setup-sh7710.c
@@ -101,7 +101,7 @@
 	},
 };
 
-void __init init_IRQ_ipr(void)
+void __init plat_irq_setup(void)
 {
 	register_ipr_controller(&ipr_irq_desc);
 }
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7750.c b/arch/sh/kernel/cpu/sh4/setup-sh7750.c
index da153bc..f2286de 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh7750.c
+++ b/arch/sh/kernel/cpu/sh4/setup-sh7750.c
@@ -82,88 +82,213 @@
 }
 __initcall(sh7750_devices_setup);
 
-static struct ipr_data ipr_irq_table[] = {
-	/* IRQ, IPR-idx, shift, priority */
-	{ 16, 0, 12, 2 }, /* TMU0 TUNI*/
-	{ 17, 0, 12, 2 }, /* TMU1 TUNI */
-	{ 18, 0,  4, 2 }, /* TMU2 TUNI */
-	{ 19, 0,  4, 2 }, /* TMU2 TIPCI */
-	{ 27, 1, 12, 2 }, /* WDT ITI */
-	{ 20, 0,  0, 2 }, /* RTC ATI (alarm) */
-	{ 21, 0,  0, 2 }, /* RTC PRI (period) */
-	{ 22, 0,  0, 2 }, /* RTC CUI (carry) */
-	{ 23, 1,  4, 3 }, /* SCI ERI */
-	{ 24, 1,  4, 3 }, /* SCI RXI */
-	{ 25, 1,  4, 3 }, /* SCI TXI */
-	{ 40, 2,  4, 3 }, /* SCIF ERI */
-	{ 41, 2,  4, 3 }, /* SCIF RXI */
-	{ 42, 2,  4, 3 }, /* SCIF BRI */
-	{ 43, 2,  4, 3 }, /* SCIF TXI */
-	{ 34, 2,  8, 7 }, /* DMAC DMTE0 */
-	{ 35, 2,  8, 7 }, /* DMAC DMTE1 */
-	{ 36, 2,  8, 7 }, /* DMAC DMTE2 */
-	{ 37, 2,  8, 7 }, /* DMAC DMTE3 */
-	{ 38, 2,  8, 7 }, /* DMAC DMAE */
+enum {
+	UNUSED = 0,
+
+	/* interrupt sources */
+	IRL0, IRL1, IRL2, IRL3, /* only IRLM mode supported */
+	HUDI, GPIOI,
+	DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2, DMAC_DMTE3,
+	DMAC_DMTE4, DMAC_DMTE5, DMAC_DMTE6, DMAC_DMTE7,
+	DMAC_DMAE,
+	PCIC0_PCISERR, PCIC1_PCIERR, PCIC1_PCIPWDWN, PCIC1_PCIPWON,
+	PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2, PCIC1_PCIDMA3,
+	TMU3, TMU4, TMU0, TMU1, TMU2_TUNI, TMU2_TICPI,
+	RTC_ATI, RTC_PRI, RTC_CUI,
+	SCI1_ERI, SCI1_RXI, SCI1_TXI, SCI1_TEI,
+	SCIF_ERI, SCIF_RXI, SCIF_BRI, SCIF_TXI,
+	WDT,
+	REF_RCMI, REF_ROVI,
+
+	/* interrupt groups */
+	DMAC, PCIC1, TMU2, RTC, SCI1, SCIF, REF,
 };
 
-static unsigned long ipr_offsets[] = {
-	0xffd00004UL,	/* 0: IPRA */
-	0xffd00008UL,	/* 1: IPRB */
-	0xffd0000cUL,	/* 2: IPRC */
-	0xffd00010UL,	/* 3: IPRD */
+static struct intc_vect vectors[] = {
+	INTC_VECT(HUDI, 0x600), INTC_VECT(GPIOI, 0x620),
+	INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420),
+	INTC_VECT(TMU2_TUNI, 0x440), INTC_VECT(TMU2_TICPI, 0x460),
+	INTC_VECT(RTC_ATI, 0x480), INTC_VECT(RTC_PRI, 0x4a0),
+	INTC_VECT(RTC_CUI, 0x4c0),
+	INTC_VECT(SCI1_ERI, 0x4e0), INTC_VECT(SCI1_RXI, 0x500),
+	INTC_VECT(SCI1_TXI, 0x520), INTC_VECT(SCI1_TEI, 0x540),
+	INTC_VECT(SCIF_ERI, 0x700), INTC_VECT(SCIF_RXI, 0x720),
+	INTC_VECT(SCIF_BRI, 0x740), INTC_VECT(SCIF_TXI, 0x760),
+	INTC_VECT(WDT, 0x560),
+	INTC_VECT(REF_RCMI, 0x580), INTC_VECT(REF_ROVI, 0x5a0),
 };
 
-static struct ipr_desc ipr_irq_desc = {
-	.ipr_offsets	= ipr_offsets,
-	.nr_offsets	= ARRAY_SIZE(ipr_offsets),
-
-	.ipr_data	= ipr_irq_table,
-	.nr_irqs	= ARRAY_SIZE(ipr_irq_table),
-
-	.chip = {
-		.name	= "IPR-sh7750",
-	},
+static struct intc_group groups[] = {
+	INTC_GROUP(TMU2, TMU2_TUNI, TMU2_TICPI),
+	INTC_GROUP(RTC, RTC_ATI, RTC_PRI, RTC_CUI),
+	INTC_GROUP(SCI1, SCI1_ERI, SCI1_RXI, SCI1_TXI, SCI1_TEI),
+	INTC_GROUP(SCIF, SCIF_ERI, SCIF_RXI, SCIF_BRI, SCIF_TXI),
+	INTC_GROUP(REF, REF_RCMI, REF_ROVI),
 };
 
-#ifdef CONFIG_CPU_SUBTYPE_SH7751
-static struct ipr_data ipr_irq_table_sh7751[] = {
-	{ 44, 2,  8, 7 }, /* DMAC DMTE4 */
-	{ 45, 2,  8, 7 }, /* DMAC DMTE5 */
-	{ 46, 2,  8, 7 }, /* DMAC DMTE6 */
-	{ 47, 2,  8, 7 }, /* DMAC DMTE7 */
-	/* The following use INTC_INPRI00 for masking, which is a 32-bit
-	   register, not a 16-bit register like the IPRx registers, so it
-	   would need special support */
-	/*{ 72, INTPRI00,  8, ? },*/ /* TMU3 TUNI */
-	/*{ 76, INTPRI00, 12, ? },*/ /* TMU4 TUNI */
+static struct intc_prio priorities[] = {
+	INTC_PRIO(SCIF, 3),
+	INTC_PRIO(SCI1, 3),
+	INTC_PRIO(DMAC, 7),
 };
 
-static struct ipr_desc ipr_irq_desc_sh7751 = {
-	.ipr_offsets	= ipr_offsets,
-	.nr_offsets	= ARRAY_SIZE(ipr_offsets),
-
-	.ipr_data	= ipr_irq_table_sh7751,
-	.nr_irqs	= ARRAY_SIZE(ipr_irq_table_sh7751),
-
-	.chip = {
-		.name	= "IPR-sh7751",
-	},
+static struct intc_prio_reg prio_registers[] = {
+	{ 0xffd00004, 16, 4, /* IPRA */ { TMU0, TMU1, TMU2, RTC } },
+	{ 0xffd00008, 16, 4, /* IPRB */ { WDT, REF, SCI1, 0 } },
+	{ 0xffd0000c, 16, 4, /* IPRC */ { GPIOI, DMAC, SCIF, HUDI } },
+	{ 0xffd00010, 16, 4, /* IPRD */ { IRL0, IRL1, IRL2, IRL3 } },
+	{ 0xfe080000, 32, 4, /* INTPRI00 */ { 0, 0, 0, 0,
+					      TMU4, TMU3,
+					      PCIC1, PCIC0_PCISERR } },
 };
+
+static DECLARE_INTC_DESC(intc_desc, "sh7750", vectors, groups,
+			 priorities, NULL, prio_registers, NULL);
+
+/* SH7750, SH7750S, SH7751 and SH7091 all have 4-channel DMA controllers */
+#if defined(CONFIG_CPU_SUBTYPE_SH7750) || \
+	defined(CONFIG_CPU_SUBTYPE_SH7750S) || \
+	defined(CONFIG_CPU_SUBTYPE_SH7751) || \
+	defined(CONFIG_CPU_SUBTYPE_SH7091)
+static struct intc_vect vectors_dma4[] = {
+	INTC_VECT(DMAC_DMTE0, 0x640), INTC_VECT(DMAC_DMTE1, 0x660),
+	INTC_VECT(DMAC_DMTE2, 0x680), INTC_VECT(DMAC_DMTE3, 0x6a0),
+	INTC_VECT(DMAC_DMAE, 0x6c0),
+};
+
+static struct intc_group groups_dma4[] = {
+	INTC_GROUP(DMAC, DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2,
+		   DMAC_DMTE3, DMAC_DMAE),
+};
+
+static DECLARE_INTC_DESC(intc_desc_dma4, "sh7750_dma4",
+			 vectors_dma4, groups_dma4,
+			 priorities, NULL, prio_registers, NULL);
 #endif
 
-void __init init_IRQ_ipr(void)
+/* SH7750R and SH7751R both have 8-channel DMA controllers */
+#if defined(CONFIG_CPU_SUBTYPE_SH7750R) || defined(CONFIG_CPU_SUBTYPE_SH7751R)
+static struct intc_vect vectors_dma8[] = {
+	INTC_VECT(DMAC_DMTE0, 0x640), INTC_VECT(DMAC_DMTE1, 0x660),
+	INTC_VECT(DMAC_DMTE2, 0x680), INTC_VECT(DMAC_DMTE3, 0x6a0),
+	INTC_VECT(DMAC_DMTE4, 0x780), INTC_VECT(DMAC_DMTE5, 0x7a0),
+	INTC_VECT(DMAC_DMTE6, 0x7c0), INTC_VECT(DMAC_DMTE7, 0x7e0),
+	INTC_VECT(DMAC_DMAE, 0x6c0),
+};
+
+static struct intc_group groups_dma8[] = {
+	INTC_GROUP(DMAC, DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2,
+		   DMAC_DMTE3, DMAC_DMTE4, DMAC_DMTE5,
+		   DMAC_DMTE6, DMAC_DMTE7, DMAC_DMAE),
+};
+
+static DECLARE_INTC_DESC(intc_desc_dma8, "sh7750_dma8",
+			 vectors_dma8, groups_dma8,
+			 priorities, NULL, prio_registers, NULL);
+#endif
+
+/* SH7750R, SH7751 and SH7751R all have two extra timer channels */
+#if defined(CONFIG_CPU_SUBTYPE_SH7750R) || \
+	defined(CONFIG_CPU_SUBTYPE_SH7751) || \
+	defined(CONFIG_CPU_SUBTYPE_SH7751R)
+static struct intc_vect vectors_tmu34[] = {
+	INTC_VECT(TMU3, 0xb00), INTC_VECT(TMU4, 0xb80),
+};
+
+static struct intc_mask_reg mask_registers[] = {
+	{ 0xfe080040, 0xfe080060, 32, /* INTMSK00 / INTMSKCLR00 */
+	  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	    0, 0, 0, 0, 0, 0, TMU4, TMU3,
+	    PCIC1_PCIERR, PCIC1_PCIPWDWN, PCIC1_PCIPWON,
+	    PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2,
+	    PCIC1_PCIDMA3, PCIC0_PCISERR } },
+};
+
+static DECLARE_INTC_DESC(intc_desc_tmu34, "sh7750_tmu34",
+			 vectors_tmu34, NULL, priorities,
+			 mask_registers, prio_registers, NULL);
+#endif
+
+/* SH7750S, SH7750R, SH7751 and SH7751R all have IRLM priority registers */
+static struct intc_vect vectors_irlm[] = {
+	INTC_VECT(IRL0, 0x240), INTC_VECT(IRL1, 0x2a0),
+	INTC_VECT(IRL2, 0x300), INTC_VECT(IRL3, 0x360),
+};
+
+static DECLARE_INTC_DESC(intc_desc_irlm, "sh7750_irlm", vectors_irlm, NULL,
+			 priorities, NULL, prio_registers, NULL);
+
+/* SH7751 and SH7751R both have PCI */
+#if defined(CONFIG_CPU_SUBTYPE_SH7751) || defined(CONFIG_CPU_SUBTYPE_SH7751R)
+static struct intc_vect vectors_pci[] = {
+	INTC_VECT(PCIC0_PCISERR, 0xa00), INTC_VECT(PCIC1_PCIERR, 0xae0),
+	INTC_VECT(PCIC1_PCIPWDWN, 0xac0), INTC_VECT(PCIC1_PCIPWON, 0xaa0),
+	INTC_VECT(PCIC1_PCIDMA0, 0xa80), INTC_VECT(PCIC1_PCIDMA1, 0xa60),
+	INTC_VECT(PCIC1_PCIDMA2, 0xa40), INTC_VECT(PCIC1_PCIDMA3, 0xa20),
+};
+
+static struct intc_group groups_pci[] = {
+	INTC_GROUP(PCIC1, PCIC1_PCIERR, PCIC1_PCIPWDWN, PCIC1_PCIPWON,
+		   PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2, PCIC1_PCIDMA3),
+};
+
+static DECLARE_INTC_DESC(intc_desc_pci, "sh7750_pci", vectors_pci, groups_pci,
+			 priorities, mask_registers, prio_registers, NULL);
+#endif
+
+#if defined(CONFIG_CPU_SUBTYPE_SH7750) || \
+	defined(CONFIG_CPU_SUBTYPE_SH7750S) || \
+	defined(CONFIG_CPU_SUBTYPE_SH7091)
+void __init plat_irq_setup(void)
 {
-	register_ipr_controller(&ipr_irq_desc);
-#ifdef CONFIG_CPU_SUBTYPE_SH7751
-	register_ipr_controller(&ipr_irq_desc_sh7751);
-#endif
+	/*
+	 * same vectors for SH7750, SH7750S and SH7091 except for IRLM,
+	 * see below..
+	 */
+	register_intc_controller(&intc_desc);
+	register_intc_controller(&intc_desc_dma4);
 }
+#endif
+
+#if defined(CONFIG_CPU_SUBTYPE_SH7750R)
+void __init plat_irq_setup(void)
+{
+	register_intc_controller(&intc_desc);
+	register_intc_controller(&intc_desc_dma8);
+	register_intc_controller(&intc_desc_tmu34);
+}
+#endif
+
+#if defined(CONFIG_CPU_SUBTYPE_SH7751)
+void __init plat_irq_setup(void)
+{
+	register_intc_controller(&intc_desc);
+	register_intc_controller(&intc_desc_dma4);
+	register_intc_controller(&intc_desc_tmu34);
+	register_intc_controller(&intc_desc_pci);
+}
+#endif
+
+#if defined(CONFIG_CPU_SUBTYPE_SH7751R)
+void __init plat_irq_setup(void)
+{
+	register_intc_controller(&intc_desc);
+	register_intc_controller(&intc_desc_dma8);
+	register_intc_controller(&intc_desc_tmu34);
+	register_intc_controller(&intc_desc_pci);
+}
+#endif
 
 #define INTC_ICR	0xffd00000UL
 #define INTC_ICR_IRLM   (1<<7)
 
 /* enable individual interrupt mode for external interupts */
-void ipr_irq_enable_irlm(void)
+void __init ipr_irq_enable_irlm(void)
 {
+#if defined(CONFIG_CPU_SUBTYPE_SH7750) || defined(CONFIG_CPU_SUBTYPE_SH7091)
+	BUG(); /* impossible to mask interrupts on SH7750 and SH7091 */
+#endif
+	register_intc_controller(&intc_desc_irlm);
+
 	ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR);
 }
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7760.c b/arch/sh/kernel/cpu/sh4/setup-sh7760.c
index 3df1697..47fa270 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh7760.c
+++ b/arch/sh/kernel/cpu/sh4/setup-sh7760.c
@@ -109,11 +109,6 @@
 	},
 };
 
-void __init init_IRQ_intc2(void)
-{
-	register_intc2_controller(&intc2_irq_desc);
-}
-
 static struct ipr_data ipr_irq_table[] = {
 	/* IRQ, IPR-idx, shift, priority */
 	{ 16, 0, 12, 2 }, /* TMU0 TUNI*/
@@ -163,7 +158,8 @@
 	},
 };
 
-void __init init_IRQ_ipr(void)
+void __init plat_irq_setup(void)
 {
+	register_intc2_controller(&intc2_irq_desc);
 	register_ipr_controller(&ipr_irq_desc);
 }
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
index 51b386d..a0fd8bb 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
@@ -387,9 +387,24 @@
 	return err;
 }
 
+static long sh7722_frqcr_round_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent_rate = clk->parent->rate;
+	int div;
+
+	/* look for multiplier/divisor pair */
+	div = sh7722_find_divisors(parent_rate, rate);
+	if (div < 0)
+		return clk->rate;
+
+	/* calculate new value of clock rate */
+	return parent_rate * 2 / div;
+}
+
 static struct clk_ops sh7722_frqcr_clk_ops = {
 	.recalc = sh7722_frqcr_recalc,
 	.set_rate = sh7722_frqcr_set_rate,
+	.round_rate = sh7722_frqcr_round_rate,
 };
 
 /*
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
index a3e159e..25b913e 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
@@ -19,8 +19,21 @@
 		.mapbase	= 0xffe00000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
-		.irqs		= { 80, 81, 83, 82 },
-	}, {
+		.irqs		= { 80, 80, 80, 80 },
+	},
+	{
+		.mapbase	= 0xffe10000,
+		.flags		= UPF_BOOT_AUTOCONF,
+		.type		= PORT_SCIF,
+		.irqs		= { 81, 81, 81, 81 },
+	},
+	{
+		.mapbase	= 0xffe20000,
+		.flags		= UPF_BOOT_AUTOCONF,
+		.type		= PORT_SCIF,
+		.irqs		= { 82, 82, 82, 82 },
+	},
+	{
 		.flags = 0,
 	}
 };
@@ -44,46 +57,145 @@
 }
 __initcall(sh7722_devices_setup);
 
-static struct ipr_data ipr_irq_table[] = {
-	/* IRQ, IPR-idx, shift, prio */
-	{ 16, 0, 12, 2 }, /* TMU0 */
-	{ 17, 0,  8, 2 }, /* TMU1 */
-	{ 80, 6, 12, 3 }, /* SCIF ERI */
-	{ 81, 6, 12, 3 }, /* SCIF RXI */
-	{ 82, 6, 12, 3 }, /* SCIF BRI */
-	{ 83, 6, 12, 3 }, /* SCIF TXI */
+enum {
+	UNUSED=0,
+
+	/* interrupt sources */
+	IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
+	HUDI,
+	SIM_ERI, SIM_RXI, SIM_TXI, SIM_TEI,
+	RTC_ATI, RTC_PRI, RTC_CUI,
+	DMAC0, DMAC1, DMAC2, DMAC3,
+	VIO_CEUI, VIO_BEUI, VIO_VEUI, VOU,
+	VPU, TPU,
+	USB_USBI0, USB_USBI1,
+	DMAC4, DMAC5, DMAC_DADERR,
+	KEYSC,
+	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,
+
+	/* interrupt groups */
+
+	SIM, RTC, DMAC0123, VIOVOU, USB, DMAC45, FLCTL, I2C, SDHI,
 };
 
-static unsigned long ipr_offsets[] = {
-	0xa4080000, /*  0: IPRA */
-	0xa4080004, /*  1: IPRB */
-	0xa4080008, /*  2: IPRC */
-	0xa408000c, /*  3: IPRD */
-	0xa4080010, /*  4: IPRE */
-	0xa4080014, /*  5: IPRF */
-	0xa4080018, /*  6: IPRG */
-	0xa408001c, /*  7: IPRH */
-	0xa4080020, /*  8: IPRI */
-	0xa4080024, /*  9: IPRJ */
-	0xa4080028, /* 10: IPRK */
-	0xa408002c, /* 11: IPRL */
+static struct intc_vect vectors[] = {
+	INTC_VECT(IRQ0, 0x600), INTC_VECT(IRQ1, 0x620),
+	INTC_VECT(IRQ2, 0x640), INTC_VECT(IRQ3, 0x660),
+	INTC_VECT(IRQ4, 0x680), INTC_VECT(IRQ5, 0x6a0),
+	INTC_VECT(IRQ6, 0x6c0), INTC_VECT(IRQ7, 0x6e0),
+	INTC_VECT(SIM_ERI, 0x700), INTC_VECT(SIM_RXI, 0x720),
+	INTC_VECT(SIM_TXI, 0x740), INTC_VECT(SIM_TEI, 0x760),
+	INTC_VECT(RTC_ATI, 0x780), INTC_VECT(RTC_PRI, 0x7a0),
+	INTC_VECT(RTC_CUI, 0x7c0),
+	INTC_VECT(DMAC0, 0x800), INTC_VECT(DMAC1, 0x820),
+	INTC_VECT(DMAC2, 0x840), INTC_VECT(DMAC3, 0x860),
+	INTC_VECT(VIO_CEUI, 0x880), INTC_VECT(VIO_BEUI, 0x8a0),
+	INTC_VECT(VIO_VEUI, 0x8c0), INTC_VECT(VOU, 0x8e0),
+	INTC_VECT(VPU, 0x980), INTC_VECT(TPU, 0x9a0),
+	INTC_VECT(USB_USBI0, 0xa20), INTC_VECT(USB_USBI1, 0xa40),
+	INTC_VECT(DMAC4, 0xb80), INTC_VECT(DMAC5, 0xba0),
+	INTC_VECT(DMAC_DADERR, 0xbc0), INTC_VECT(KEYSC, 0xbe0),
+	INTC_VECT(SCIF0, 0xc00), INTC_VECT(SCIF1, 0xc20),
+	INTC_VECT(SCIF2, 0xc40), INTC_VECT(SIOF0, 0xc80),
+	INTC_VECT(SIOF1, 0xca0), INTC_VECT(SIO, 0xd00),
+	INTC_VECT(FLCTL_FLSTEI, 0xd80), INTC_VECT(FLCTL_FLENDI, 0xda0),
+	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(CMT, 0xf00), INTC_VECT(TSIF, 0xf20),
+	INTC_VECT(SIU, 0xf80), INTC_VECT(TWODG, 0xfa0),
+	INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420),
+	INTC_VECT(TMU2, 0x440), INTC_VECT(IRDA, 0x480),
+	INTC_VECT(JPU, 0x560), INTC_VECT(LCDC, 0x580),
 };
 
-static struct ipr_desc ipr_irq_desc = {
-	.ipr_offsets	= ipr_offsets,
-	.nr_offsets	= ARRAY_SIZE(ipr_offsets),
-
-	.ipr_data	= ipr_irq_table,
-	.nr_irqs	= ARRAY_SIZE(ipr_irq_table),
-
-	.chip = {
-		.name	= "IPR-sh7722",
-	},
+static struct intc_group groups[] = {
+	INTC_GROUP(SIM, SIM_ERI, SIM_RXI, SIM_TXI, SIM_TEI),
+	INTC_GROUP(RTC, RTC_ATI, RTC_PRI, RTC_CUI),
+	INTC_GROUP(DMAC0123, DMAC0, DMAC1, DMAC2, DMAC3),
+	INTC_GROUP(VIOVOU, VIO_CEUI, VIO_BEUI, VIO_VEUI, VOU),
+	INTC_GROUP(USB, USB_USBI0, USB_USBI1),
+	INTC_GROUP(DMAC45, DMAC4, DMAC5, DMAC_DADERR),
+	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),
 };
 
-void __init init_IRQ_ipr(void)
+static struct intc_prio priorities[] = {
+	INTC_PRIO(SCIF0, 3),
+	INTC_PRIO(SCIF1, 3),
+	INTC_PRIO(SCIF2, 3),
+	INTC_PRIO(TMU0, 2),
+	INTC_PRIO(TMU1, 2),
+};
+
+static struct intc_mask_reg mask_registers[] = {
+	{ 0xa4080080, 0xa40800c0, 8, /* IMR0 / IMCR0 */
+	  { } },
+	{ 0xa4080084, 0xa40800c4, 8, /* IMR1 / IMCR1 */
+	  { VOU, VIO_VEUI, VIO_BEUI, VIO_CEUI, DMAC3, DMAC2, DMAC1, DMAC0 } },
+	{ 0xa4080088, 0xa40800c8, 8, /* IMR2 / IMCR2 */
+	  { 0, 0, 0, VPU, } },
+	{ 0xa408008c, 0xa40800cc, 8, /* IMR3 / IMCR3 */
+	  { SIM_TEI, SIM_TXI, SIM_RXI, SIM_ERI, 0, 0, 0, IRDA } },
+	{ 0xa4080090, 0xa40800d0, 8, /* IMR4 / IMCR4 */
+	  { 0, TMU2, TMU1, TMU0, JPU, 0, 0, LCDC } },
+	{ 0xa4080094, 0xa40800d4, 8, /* IMR5 / IMCR5 */
+	  { KEYSC, DMAC_DADERR, DMAC5, DMAC4, 0, SCIF2, SCIF1, SCIF0 } },
+	{ 0xa4080098, 0xa40800d8, 8, /* IMR6 / IMCR6 */
+	  { 0, 0, 0, SIO, 0, 0, SIOF1, SIOF0 } },
+	{ 0xa408009c, 0xa40800dc, 8, /* IMR7 / IMCR7 */
+	  { 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 } },
+	{ 0xa40800a4, 0xa40800e4, 8, /* IMR9 / IMCR9 */
+	  { 0, 0, 0, CMT, 0, USB_USBI1, USB_USBI0, } },
+	{ 0xa40800a8, 0xa40800e8, 8, /* IMR10 / IMCR10 */
+	  { } },
+	{ 0xa40800ac, 0xa40800ec, 8, /* IMR11 / IMCR11 */
+	  { 0, RTC_CUI, RTC_PRI, RTC_ATI, 0, TPU, 0, TSIF } },
+	{ 0xa4140044, 0xa4140064, 8, /* INTMSK00 / INTMSKCLR00 */
+	  { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
+};
+
+static struct intc_prio_reg prio_registers[] = {
+	{ 0xa4080000, 16, 4, /* IPRA */ { TMU0, TMU1, TMU2, IRDA } },
+	{ 0xa4080004, 16, 4, /* IPRB */ { JPU, LCDC, SIM } },
+	{ 0xa4080008, 16, 4, /* IPRC */ { } },
+	{ 0xa408000c, 16, 4, /* IPRD */ { } },
+	{ 0xa4080010, 16, 4, /* IPRE */ { DMAC0123, VIOVOU, 0, VPU } },
+	{ 0xa4080014, 16, 4, /* IPRF */ { KEYSC, DMAC45, USB, CMT } },
+	{ 0xa4080018, 16, 4, /* IPRG */ { SCIF0, SCIF1, SCIF2 } },
+	{ 0xa408001c, 16, 4, /* IPRH */ { SIOF0, SIOF1, FLCTL, I2C } },
+	{ 0xa4080020, 16, 4, /* IPRI */ { SIO, 0, TSIF, RTC } },
+	{ 0xa4080024, 16, 4, /* IPRJ */ { 0, 0, SIU } },
+	{ 0xa4080028, 16, 4, /* IPRK */ { 0, 0, 0, SDHI } },
+	{ 0xa408002c, 16, 4, /* IPRL */ { TWODG, 0, TPU } },
+	{ 0xa4140010, 32, 4, /* INTPRI00 */
+	  { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
+};
+
+static struct intc_sense_reg sense_registers[] = {
+	{ 0xa414001c, 16, 2, /* ICR1 */
+	  { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
+};
+
+static DECLARE_INTC_DESC(intc_desc, "sh7722", vectors, groups, priorities,
+			 mask_registers, prio_registers, sense_registers);
+
+void __init plat_irq_setup(void)
 {
-	register_ipr_controller(&ipr_irq_desc);
+	register_intc_controller(&intc_desc);
 }
 
 void __init plat_mem_setup(void)
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
index b57c760..a4127ec 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
@@ -30,7 +30,7 @@
 	},
 	[3] = {
 		/* Alarm IRQ */
-		.start	= 23,
+		.start	= 20,
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -78,44 +78,205 @@
 }
 __initcall(sh7780_devices_setup);
 
-static struct intc2_data intc2_irq_table[] = {
-	{ 28, 0, 24, 0, 0, 2 },		/* TMU0 */
+enum {
+	UNUSED = 0,
 
-	{ 21, 1,  0, 0, 2, 2 },
-	{ 22, 1,  1, 0, 2, 2 },
-	{ 23, 1,  2, 0, 2, 2 },
+	/* interrupt sources */
 
-	{ 40, 8, 24, 0, 3, 3 },		/* SCIF0 ERI */
-	{ 41, 8, 24, 0, 3, 3 },		/* SCIF0 RXI */
-	{ 42, 8, 24, 0, 3, 3 },		/* SCIF0 BRI */
-	{ 43, 8, 24, 0, 3, 3 },		/* SCIF0 TXI */
+	IRL_LLLL, IRL_LLLH, IRL_LLHL, IRL_LLHH,
+	IRL_LHLL, IRL_LHLH, IRL_LHHL, IRL_LHHH,
+	IRL_HLLL, IRL_HLLH, IRL_HLHL, IRL_HLHH,
+	IRL_HHLL, IRL_HHLH, IRL_HHHL,
 
-	{ 76, 8, 16, 0, 4, 3 },		/* SCIF1 ERI */
-	{ 77, 8, 16, 0, 4, 3 },		/* SCIF1 RXI */
-	{ 78, 8, 16, 0, 4, 3 },		/* SCIF1 BRI */
-	{ 79, 8, 16, 0, 4, 3 },		/* SCIF1 TXI */
+	IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
+	RTC_ATI, RTC_PRI, RTC_CUI,
+	WDT,
+	TMU0, TMU1, TMU2, TMU2_TICPI,
+	HUDI,
+	DMAC0_DMINT0, DMAC0_DMINT1, DMAC0_DMINT2, DMAC0_DMINT3, DMAC0_DMAE,
+	SCIF0_ERI, SCIF0_RXI, SCIF0_BRI, SCIF0_TXI,
+	DMAC0_DMINT4, DMAC0_DMINT5, DMAC1_DMINT6, DMAC1_DMINT7,
+	CMT, HAC,
+	PCISERR, PCIINTA, PCIINTB, PCIINTC, PCIINTD,
+	PCIERR, PCIPWD3, PCIPWD2, PCIPWD1, PCIPWD0,
+	SCIF1_ERI, SCIF1_RXI, SCIF1_BRI, SCIF1_TXI,
+	SIOF, HSPI,
+	MMCIF_FSTAT, MMCIF_TRAN, MMCIF_ERR, MMCIF_FRDY,
+	DMAC1_DMINT8, DMAC1_DMINT9, DMAC1_DMINT10, DMAC1_DMINT11,
+	TMU3, TMU4, TMU5,
+	SSI,
+	FLCTL_FLSTE, FLCTL_FLEND, FLCTL_FLTRQ0, FLCTL_FLTRQ1,
+	GPIOI0, GPIOI1, GPIOI2, GPIOI3,
 
-	{ 64, 0x10,  8, 0, 14, 2 },	/* PCIC0 */
-	{ 65, 0x10,  0, 0, 15, 2 },	/* PCIC1 */
-	{ 66, 0x14, 24, 0, 16, 2 },	/* PCIC2 */
-	{ 67, 0x14, 16, 0, 17, 2 },	/* PCIC3 */
-	{ 68, 0x14,  8, 0, 18, 2 },	/* PCIC4 */
+	/* interrupt groups */
+
+	RTC, TMU012, DMAC0, SCIF0, DMAC45, DMAC1,
+	PCIC5, SCIF1, MMCIF, TMU345, FLCTL, GPIO,
 };
 
-static struct intc2_desc intc2_irq_desc __read_mostly = {
-	.prio_base	= 0xffd40000,
-	.msk_base	= 0xffd40038,
-	.mskclr_base	= 0xffd4003c,
-
-	.intc2_data	= intc2_irq_table,
-	.nr_irqs	= ARRAY_SIZE(intc2_irq_table),
-
-	.chip = {
-		.name	= "INTC2-sh7780",
-	},
+static struct intc_vect vectors[] = {
+	INTC_VECT(RTC_ATI, 0x480), INTC_VECT(RTC_PRI, 0x4a0),
+	INTC_VECT(RTC_CUI, 0x4c0),
+	INTC_VECT(WDT, 0x560),
+	INTC_VECT(TMU0, 0x580), INTC_VECT(TMU1, 0x5a0),
+	INTC_VECT(TMU2, 0x5c0), INTC_VECT(TMU2_TICPI, 0x5e0),
+	INTC_VECT(HUDI, 0x600),
+	INTC_VECT(DMAC0_DMINT0, 0x640), INTC_VECT(DMAC0_DMINT1, 0x660),
+	INTC_VECT(DMAC0_DMINT2, 0x680), INTC_VECT(DMAC0_DMINT3, 0x6a0),
+	INTC_VECT(DMAC0_DMAE, 0x6c0),
+	INTC_VECT(SCIF0_ERI, 0x700), INTC_VECT(SCIF0_RXI, 0x720),
+	INTC_VECT(SCIF0_BRI, 0x740), INTC_VECT(SCIF0_TXI, 0x760),
+	INTC_VECT(DMAC0_DMINT4, 0x780), INTC_VECT(DMAC0_DMINT5, 0x7a0),
+	INTC_VECT(DMAC1_DMINT6, 0x7c0), INTC_VECT(DMAC1_DMINT7, 0x7e0),
+	INTC_VECT(CMT, 0x900), INTC_VECT(HAC, 0x980),
+	INTC_VECT(PCISERR, 0xa00), INTC_VECT(PCIINTA, 0xa20),
+	INTC_VECT(PCIINTB, 0xa40), INTC_VECT(PCIINTC, 0xa60),
+	INTC_VECT(PCIINTD, 0xa80), INTC_VECT(PCIERR, 0xaa0),
+	INTC_VECT(PCIPWD3, 0xac0), INTC_VECT(PCIPWD2, 0xae0),
+	INTC_VECT(PCIPWD1, 0xb00), INTC_VECT(PCIPWD0, 0xb20),
+	INTC_VECT(SCIF1_ERI, 0xb80), INTC_VECT(SCIF1_RXI, 0xba0),
+	INTC_VECT(SCIF1_BRI, 0xbc0), INTC_VECT(SCIF1_TXI, 0xbe0),
+	INTC_VECT(SIOF, 0xc00), INTC_VECT(HSPI, 0xc80),
+	INTC_VECT(MMCIF_FSTAT, 0xd00), INTC_VECT(MMCIF_TRAN, 0xd20),
+	INTC_VECT(MMCIF_ERR, 0xd40), INTC_VECT(MMCIF_FRDY, 0xd60),
+	INTC_VECT(DMAC1_DMINT8, 0xd80), INTC_VECT(DMAC1_DMINT9, 0xda0),
+	INTC_VECT(DMAC1_DMINT10, 0xdc0), INTC_VECT(DMAC1_DMINT11, 0xde0),
+	INTC_VECT(TMU3, 0xe00), INTC_VECT(TMU4, 0xe20),
+	INTC_VECT(TMU5, 0xe40),
+	INTC_VECT(SSI, 0xe80),
+	INTC_VECT(FLCTL_FLSTE, 0xf00), INTC_VECT(FLCTL_FLEND, 0xf20),
+	INTC_VECT(FLCTL_FLTRQ0, 0xf40), INTC_VECT(FLCTL_FLTRQ1, 0xf60),
+	INTC_VECT(GPIOI0, 0xf80), INTC_VECT(GPIOI1, 0xfa0),
+	INTC_VECT(GPIOI2, 0xfc0), INTC_VECT(GPIOI3, 0xfe0),
 };
 
-void __init init_IRQ_intc2(void)
+static struct intc_group groups[] = {
+	INTC_GROUP(RTC, RTC_ATI, RTC_PRI, RTC_CUI),
+	INTC_GROUP(TMU012, TMU0, TMU1, TMU2, TMU2_TICPI),
+	INTC_GROUP(DMAC0, DMAC0_DMINT0, DMAC0_DMINT1, DMAC0_DMINT2,
+		   DMAC0_DMINT3, DMAC0_DMINT4, DMAC0_DMINT5, DMAC0_DMAE),
+	INTC_GROUP(SCIF0, SCIF0_ERI, SCIF0_RXI, SCIF0_BRI, SCIF0_TXI),
+	INTC_GROUP(DMAC1, DMAC1_DMINT6, DMAC1_DMINT7, DMAC1_DMINT8,
+		   DMAC1_DMINT9, DMAC1_DMINT10, DMAC1_DMINT11),
+	INTC_GROUP(PCIC5, PCIERR, PCIPWD3, PCIPWD2, PCIPWD1, PCIPWD0),
+	INTC_GROUP(SCIF1, SCIF1_ERI, SCIF1_RXI, SCIF1_BRI, SCIF1_TXI),
+	INTC_GROUP(MMCIF, MMCIF_FSTAT, MMCIF_TRAN, MMCIF_ERR, MMCIF_FRDY),
+	INTC_GROUP(TMU345, TMU3, TMU4, TMU5),
+	INTC_GROUP(FLCTL, FLCTL_FLSTE, FLCTL_FLEND,
+		   FLCTL_FLTRQ0, FLCTL_FLTRQ1),
+	INTC_GROUP(GPIO, GPIOI0, GPIOI1, GPIOI2, GPIOI3),
+};
+
+static struct intc_prio priorities[] = {
+	INTC_PRIO(SCIF0, 3),
+	INTC_PRIO(SCIF1, 3),
+};
+
+static struct intc_mask_reg mask_registers[] = {
+	{ 0xffd40038, 0xffd4003c, 32, /* INT2MSKR / INT2MSKCR */
+	  { 0, 0, 0, 0, 0, 0, GPIO, FLCTL,
+	    SSI, MMCIF, HSPI, SIOF, PCIC5, PCIINTD, PCIINTC, PCIINTB,
+	    PCIINTA, PCISERR, HAC, CMT, 0, 0, DMAC1, DMAC0,
+	    HUDI, 0, WDT, SCIF1, SCIF0, RTC, TMU345, TMU012 } },
+};
+
+static struct intc_prio_reg prio_registers[] = {
+	{ 0xffd40000, 32, 8, /* INT2PRI0 */ { TMU0, TMU1, TMU2, TMU2_TICPI } },
+	{ 0xffd40004, 32, 8, /* INT2PRI1 */ { TMU3, TMU4, TMU5, RTC } },
+	{ 0xffd40008, 32, 8, /* INT2PRI2 */ { SCIF0, SCIF1, WDT } },
+	{ 0xffd4000c, 32, 8, /* INT2PRI3 */ { HUDI, DMAC0, DMAC1 } },
+	{ 0xffd40010, 32, 8, /* INT2PRI4 */ { CMT, HAC, PCISERR, PCIINTA, } },
+	{ 0xffd40014, 32, 8, /* INT2PRI5 */ { PCIINTB, PCIINTC,
+					      PCIINTD, PCIC5 } },
+	{ 0xffd40018, 32, 8, /* INT2PRI6 */ { SIOF, HSPI, MMCIF, SSI } },
+	{ 0xffd4001c, 32, 8, /* INT2PRI7 */ { FLCTL, GPIO } },
+};
+
+static DECLARE_INTC_DESC(intc_desc, "sh7780", vectors, groups, priorities,
+			 mask_registers, prio_registers, NULL);
+
+/* Support for external interrupt pins in IRQ mode */
+
+static struct intc_vect irq_vectors[] = {
+	INTC_VECT(IRQ0, 0x240), INTC_VECT(IRQ1, 0x280),
+	INTC_VECT(IRQ2, 0x2c0), INTC_VECT(IRQ3, 0x300),
+	INTC_VECT(IRQ4, 0x340), INTC_VECT(IRQ5, 0x380),
+	INTC_VECT(IRQ6, 0x3c0), INTC_VECT(IRQ7, 0x200),
+};
+
+static struct intc_mask_reg irq_mask_registers[] = {
+	{ 0xffd00044, 0xffd00064, 32, /* INTMSK0 / INTMSKCLR0 */
+	  { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
+};
+
+static struct intc_prio_reg irq_prio_registers[] = {
+	{ 0xffd00010, 32, 4, /* INTPRI */ { IRQ0, IRQ1, IRQ2, IRQ3,
+					    IRQ4, IRQ5, IRQ6, IRQ7 } },
+};
+
+static struct intc_sense_reg irq_sense_registers[] = {
+	{ 0xffd0001c, 32, 2, /* ICR1 */   { IRQ0, IRQ1, IRQ2, IRQ3,
+					    IRQ4, IRQ5, IRQ6, IRQ7 } },
+};
+
+static DECLARE_INTC_DESC(intc_irq_desc, "sh7780-irq", irq_vectors,
+			 NULL, NULL, irq_mask_registers, irq_prio_registers,
+			 irq_sense_registers);
+
+/* External interrupt pins in IRL mode */
+
+static struct intc_vect irl_vectors[] = {
+	INTC_VECT(IRL_LLLL, 0x200), INTC_VECT(IRL_LLLH, 0x220),
+	INTC_VECT(IRL_LLHL, 0x240), INTC_VECT(IRL_LLHH, 0x260),
+	INTC_VECT(IRL_LHLL, 0x280), INTC_VECT(IRL_LHLH, 0x2a0),
+	INTC_VECT(IRL_LHHL, 0x2c0), INTC_VECT(IRL_LHHH, 0x2e0),
+	INTC_VECT(IRL_HLLL, 0x300), INTC_VECT(IRL_HLLH, 0x320),
+	INTC_VECT(IRL_HLHL, 0x340), INTC_VECT(IRL_HLHH, 0x360),
+	INTC_VECT(IRL_HHLL, 0x380), INTC_VECT(IRL_HHLH, 0x3a0),
+	INTC_VECT(IRL_HHHL, 0x3c0),
+};
+
+static struct intc_mask_reg irl3210_mask_registers[] = {
+	{ 0xffd00080, 0xffd00084, 32, /* INTMSK2 / INTMSKCLR2 */
+	  { IRL_LLLL, IRL_LLLH, IRL_LLHL, IRL_LLHH,
+	    IRL_LHLL, IRL_LHLH, IRL_LHHL, IRL_LHHH,
+	    IRL_HLLL, IRL_HLLH, IRL_HLHL, IRL_HLHH,
+	    IRL_HHLL, IRL_HHLH, IRL_HHHL, } },
+};
+
+static struct intc_mask_reg irl7654_mask_registers[] = {
+	{ 0xffd00080, 0xffd00084, 32, /* INTMSK2 / INTMSKCLR2 */
+	  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	    IRL_LLLL, IRL_LLLH, IRL_LLHL, IRL_LLHH,
+	    IRL_LHLL, IRL_LHLH, IRL_LHHL, IRL_LHHH,
+	    IRL_HLLL, IRL_HLLH, IRL_HLHL, IRL_HLHH,
+	    IRL_HHLL, IRL_HHLH, IRL_HHHL, } },
+};
+
+static DECLARE_INTC_DESC(intc_irl7654_desc, "sh7780-irl7654", irl_vectors,
+			 NULL, NULL, irl7654_mask_registers, NULL, NULL);
+
+static DECLARE_INTC_DESC(intc_irl3210_desc, "sh7780-irl3210", irl_vectors,
+			 NULL, NULL, irl3210_mask_registers, NULL, NULL);
+
+void __init plat_irq_setup(void)
 {
-	register_intc2_controller(&intc2_irq_desc);
+	register_intc_controller(&intc_desc);
+}
+
+void __init plat_irq_setup_pins(int mode)
+{
+	switch (mode) {
+	case IRQ_MODE_IRQ:
+		register_intc_controller(&intc_irq_desc);
+		break;
+	case IRQ_MODE_IRL7654:
+		register_intc_controller(&intc_irl7654_desc);
+		break;
+	case IRQ_MODE_IRL3210:
+		register_intc_controller(&intc_irl3210_desc);
+		break;
+	default:
+		BUG();
+	}
 }
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
index ce10ec5..cf04756 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
@@ -110,7 +110,7 @@
 	},
 };
 
-void __init init_IRQ_intc2(void)
+void __init plat_irq_setup(void)
 {
 	register_intc2_controller(&intc2_irq_desc);
 }
diff --git a/arch/sh/kernel/cpu/sh4a/setup-shx3.c b/arch/sh/kernel/cpu/sh4a/setup-shx3.c
index 70683ea..704c064 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-shx3.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-shx3.c
@@ -79,7 +79,7 @@
 	},
 };
 
-void __init init_IRQ_intc2(void)
+void __init plat_irq_setup(void)
 {
 	register_intc2_controller(&intc2_irq_desc);
 }
diff --git a/arch/sh/kernel/cpufreq.c b/arch/sh/kernel/cpufreq.c
index 47abf6e..e618902 100644
--- a/arch/sh/kernel/cpufreq.c
+++ b/arch/sh/kernel/cpufreq.c
@@ -3,89 +3,46 @@
  *
  * cpufreq driver for the SuperH processors.
  *
- * Copyright (C) 2002, 2003, 2004, 2005 Paul Mundt
+ * Copyright (C) 2002 - 2007 Paul Mundt
  * Copyright (C) 2002 M. R. Brown
  *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
+ * Clock framework bits from arch/avr32/mach-at32ap/cpufreq.c
+ *
+ *   Copyright (C) 2004-2007 Atmel Corporation
+ *
+ * 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/types.h>
 #include <linux/cpufreq.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/slab.h>
 #include <linux/init.h>
-#include <linux/delay.h>
+#include <linux/err.h>
 #include <linux/cpumask.h>
 #include <linux/smp.h>
 #include <linux/sched.h>	/* set_cpus_allowed() */
+#include <linux/clk.h>
 
-#include <asm/processor.h>
-#include <asm/watchdog.h>
-#include <asm/freq.h>
-#include <asm/io.h>
+static struct clk *cpuclk;
 
-/*
- * For SuperH, each policy change requires that we change the IFC, BFC, and
- * PFC at the same time.  Here we define sane values that won't trash the
- * system.
- *
- * Note the max set is computed at runtime, we use the divisors that we booted
- * with to setup our maximum operating frequencies.
- */
-struct clock_set {
-	unsigned int ifc;
-	unsigned int bfc;
-	unsigned int pfc;
-} clock_sets[] = {
-#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH2)
-	{ 0, 0, 0 },	/* not implemented yet */
-#elif defined(CONFIG_CPU_SH4)
-	{ 4, 8, 8 },	/* min - IFC: 1/4, BFC: 1/8, PFC: 1/8 */
-	{ 1, 2, 2 },	/* max - IFC: 1, BFC: 1/2, PFC: 1/2 */
-#endif
-};
-
-#define MIN_CLOCK_SET	0
-#define MAX_CLOCK_SET	(ARRAY_SIZE(clock_sets) - 1)
-
-/*
- * For the time being, we only support two frequencies, which in turn are
- * aimed at the POWERSAVE and PERFORMANCE policies, which in turn are derived
- * directly from the respective min/max clock sets. Technically we could
- * support a wider range of frequencies, but these vary far too much for each
- * CPU subtype (and we'd have to construct a frequency table for each subtype).
- *
- * Maybe something to implement in the future..
- */
-#define SH_FREQ_MAX	0
-#define SH_FREQ_MIN	1
-
-static struct cpufreq_frequency_table sh_freqs[] = {
-	{ SH_FREQ_MAX,	0 },
-	{ SH_FREQ_MIN,	0 },
-	{ 0,		CPUFREQ_TABLE_END },
-};
-
-static void sh_cpufreq_update_clocks(unsigned int set)
+static unsigned int sh_cpufreq_get(unsigned int cpu)
 {
-	current_cpu_data.cpu_clock = current_cpu_data.master_clock / clock_sets[set].ifc;
-	current_cpu_data.bus_clock = current_cpu_data.master_clock / clock_sets[set].bfc;
-	current_cpu_data.module_clock = current_cpu_data.master_clock / clock_sets[set].pfc;
-	current_cpu_data.loops_per_jiffy = loops_per_jiffy;
+	return (clk_get_rate(cpuclk) + 500) / 1000;
 }
 
-/* XXX: This needs to be split out per CPU and CPU subtype. */
 /*
  * Here we notify other drivers of the proposed change and the final change.
  */
-static int sh_cpufreq_setstate(unsigned int cpu, unsigned int set)
+static int sh_cpufreq_target(struct cpufreq_policy *policy,
+			     unsigned int target_freq,
+			     unsigned int relation)
 {
-	unsigned short frqcr = ctrl_inw(FRQCR);
+	unsigned int cpu = policy->cpu;
 	cpumask_t cpus_allowed;
 	struct cpufreq_freqs freqs;
+	long freq;
 
 	if (!cpu_online(cpu))
 		return -ENODEV;
@@ -95,125 +52,109 @@
 
 	BUG_ON(smp_processor_id() != cpu);
 
-	freqs.cpu = cpu;
-	freqs.old = current_cpu_data.cpu_clock / 1000;
-	freqs.new = (current_cpu_data.master_clock / clock_sets[set].ifc) / 1000;
+	/* Convert target_freq from kHz to Hz */
+	freq = clk_round_rate(cpuclk, target_freq * 1000);
+
+	if (freq < (policy->min * 1000) || freq > (policy->max * 1000))
+		return -EINVAL;
+
+	pr_debug("cpufreq: requested frequency %u Hz\n", target_freq * 1000);
+
+	freqs.cpu	= cpu;
+	freqs.old	= sh_cpufreq_get(cpu);
+	freqs.new	= (freq + 500) / 1000;
+	freqs.flags	= 0;
 
 	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-#if defined(CONFIG_CPU_SH3)
-	frqcr |= (newstate & 0x4000) << 14;
-	frqcr |= (newstate & 0x000c) <<  2;
-#elif defined(CONFIG_CPU_SH4)
-	/*
-	 * FRQCR.PLL2EN is 1, we need to allow the PLL to stabilize by
-	 * initializing the WDT.
-	 */
-	if (frqcr & (1 << 9)) {
-		__u8 csr;
-
-		/*
-		 * Set the overflow period to the highest available,
-		 * in this case a 1/4096 division ratio yields a 5.25ms
-		 * overflow period. See asm-sh/watchdog.h for more
-		 * information and a range of other divisors.
-		 */
-		csr = sh_wdt_read_csr();
-		csr |= WTCSR_CKS_4096;
-		sh_wdt_write_csr(csr);
-
-		sh_wdt_write_cnt(0);
-	}
-	frqcr &= 0x0e00;	/* Clear ifc, bfc, pfc */
-	frqcr |= get_ifc_value(clock_sets[set].ifc) << 6;
-	frqcr |= get_bfc_value(clock_sets[set].bfc) << 3;
-	frqcr |= get_pfc_value(clock_sets[set].pfc);
-#endif
-	ctrl_outw(frqcr, FRQCR);
-	sh_cpufreq_update_clocks(set);
-
 	set_cpus_allowed(current, cpus_allowed);
+	clk_set_rate(cpuclk, freq);
 	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 
+	pr_debug("cpufreq: set frequency %lu Hz\n", freq);
+
 	return 0;
 }
 
 static int sh_cpufreq_cpu_init(struct cpufreq_policy *policy)
 {
-	unsigned int min_freq, max_freq;
-	unsigned int ifc, bfc, pfc;
+	printk(KERN_INFO "cpufreq: SuperH CPU frequency driver.\n");
 
 	if (!cpu_online(policy->cpu))
 		return -ENODEV;
 
-	/* Update our maximum clock set */
-	get_current_frequency_divisors(&ifc, &bfc, &pfc);
-	clock_sets[MAX_CLOCK_SET].ifc = ifc;
-	clock_sets[MAX_CLOCK_SET].bfc = bfc;
-	clock_sets[MAX_CLOCK_SET].pfc = pfc;
-
-	/* Convert from Hz to kHz */
-	max_freq = current_cpu_data.cpu_clock / 1000;
-	min_freq = (current_cpu_data.master_clock / clock_sets[MIN_CLOCK_SET].ifc) / 1000;
-	
-	sh_freqs[SH_FREQ_MAX].frequency = max_freq;
-	sh_freqs[SH_FREQ_MIN].frequency = min_freq;
+	cpuclk = clk_get(NULL, "cpu_clk");
+	if (IS_ERR(cpuclk)) {
+		printk(KERN_ERR "cpufreq: couldn't get CPU clk\n");
+		return PTR_ERR(cpuclk);
+	}
 
 	/* cpuinfo and default policy values */
-	policy->governor                   = CPUFREQ_DEFAULT_GOVERNOR;
+	policy->cpuinfo.min_freq = (clk_round_rate(cpuclk, 1) + 500) / 1000;
+	policy->cpuinfo.max_freq = (clk_round_rate(cpuclk, ~0UL) + 500) / 1000;
 	policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
-	policy->cur                        = max_freq;
 
-	return cpufreq_frequency_table_cpuinfo(policy, &sh_freqs[0]);
+	policy->governor	= CPUFREQ_DEFAULT_GOVERNOR;
+	policy->cur		= sh_cpufreq_get(policy->cpu);
+	policy->min		= policy->cpuinfo.min_freq;
+	policy->max		= policy->cpuinfo.max_freq;
+
+
+	/*
+	 * Catch the cases where the clock framework hasn't been wired up
+	 * properly to support scaling.
+	 */
+	if (unlikely(policy->min == policy->max)) {
+		printk(KERN_ERR "cpufreq: clock framework rate rounding "
+		       "not supported on this CPU.\n");
+
+		clk_put(cpuclk);
+		return -EINVAL;
+	}
+
+	printk(KERN_INFO "cpufreq: Frequencies - Minimum %u.%03u MHz, "
+	       "Maximum %u.%03u MHz.\n",
+	       policy->min / 1000, policy->min % 1000,
+	       policy->max / 1000, policy->max % 1000);
+
+	return 0;
 }
 
 static int sh_cpufreq_verify(struct cpufreq_policy *policy)
 {
-	return cpufreq_frequency_table_verify(policy, &sh_freqs[0]);
+	cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
+				     policy->cpuinfo.max_freq);
+	return 0;
 }
 
-static int sh_cpufreq_target(struct cpufreq_policy *policy,
-			     unsigned int target_freq,
-			     unsigned int relation)
+static int sh_cpufreq_exit(struct cpufreq_policy *policy)
 {
-	unsigned int set, idx = 0;
-
-	if (cpufreq_frequency_table_target(policy, &sh_freqs[0], target_freq, relation, &idx))
-		return -EINVAL;
-
-	set = (idx == SH_FREQ_MIN) ? MIN_CLOCK_SET : MAX_CLOCK_SET;
-
-	sh_cpufreq_setstate(policy->cpu, set);
-
+	clk_put(cpuclk);
 	return 0;
 }
 
 static struct cpufreq_driver sh_cpufreq_driver = {
 	.owner		= THIS_MODULE,
-	.name		= "SH cpufreq",
+	.name		= "sh",
 	.init		= sh_cpufreq_cpu_init,
 	.verify		= sh_cpufreq_verify,
 	.target		= sh_cpufreq_target,
+	.get		= sh_cpufreq_get,
+	.exit		= sh_cpufreq_exit,
 };
 
-static int __init sh_cpufreq_init(void)
+static int __init sh_cpufreq_module_init(void)
 {
-	if (!current_cpu_data.cpu_clock)
-		return -EINVAL;
-	if (cpufreq_register_driver(&sh_cpufreq_driver))
-		return -EINVAL;
-
-	return 0;
+	return cpufreq_register_driver(&sh_cpufreq_driver);
 }
 
-static void __exit sh_cpufreq_exit(void)
+static void __exit sh_cpufreq_module_exit(void)
 {
 	cpufreq_unregister_driver(&sh_cpufreq_driver);
 }
 
-module_init(sh_cpufreq_init);
-module_exit(sh_cpufreq_exit);
+module_init(sh_cpufreq_module_init);
+module_exit(sh_cpufreq_module_exit);
 
 MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
 MODULE_DESCRIPTION("cpufreq driver for SuperH");
 MODULE_LICENSE("GPL");
-
diff --git a/arch/sh/kernel/head.S b/arch/sh/kernel/head.S
index 71a3ad7..0bccc0c 100644
--- a/arch/sh/kernel/head.S
+++ b/arch/sh/kernel/head.S
@@ -36,7 +36,8 @@
 1:
 	.skip	PAGE_SIZE - empty_zero_page - 1b
 
-	.text	
+	.section	.text.head, "ax"
+
 /*
  * Condition at the entry of _stext:
  *
diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c
index 2789779..0340498 100644
--- a/arch/sh/kernel/irq.c
+++ b/arch/sh/kernel/irq.c
@@ -253,14 +253,7 @@
 #ifdef CONFIG_CPU_HAS_PINT_IRQ
 	init_IRQ_pint();
 #endif
-
-#ifdef CONFIG_CPU_HAS_INTC2_IRQ
-	init_IRQ_intc2();
-#endif
-
-#ifdef CONFIG_CPU_HAS_IPR_IRQ
-	init_IRQ_ipr();
-#endif
+	plat_irq_setup();
 
 	/* Perform the machine specific initialisation */
 	if (sh_mv.mv_init_irq)
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index de8e6e2..c14a3e9 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -21,6 +21,7 @@
 #include <linux/fs.h>
 #include <linux/mm.h>
 #include <linux/kexec.h>
+#include <linux/module.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/page.h>
@@ -78,7 +79,11 @@
 static struct resource code_resource = { .name = "Kernel code", };
 static struct resource data_resource = { .name = "Kernel data", };
 
-unsigned long memory_start, memory_end;
+unsigned long memory_start;
+EXPORT_SYMBOL(memory_start);
+
+unsigned long memory_end;
+EXPORT_SYMBOL(memory_end);
 
 static int __init early_parse_mem(char *p)
 {
diff --git a/arch/sh/kernel/sh_bios.c b/arch/sh/kernel/sh_bios.c
index 5b53e10b..d1bcac4 100644
--- a/arch/sh/kernel/sh_bios.c
+++ b/arch/sh/kernel/sh_bios.c
@@ -5,7 +5,7 @@
  *  Copyright (C) 2000 Greg Banks, Mitch Davis
  *
  */
-
+#include <linux/module.h>
 #include <asm/sh_bios.h>
 
 #define BIOS_CALL_CONSOLE_WRITE     	0
@@ -63,6 +63,7 @@
 {
     sh_bios_call(BIOS_CALL_GDB_DETACH, 0, 0, 0, 0);
 }
+EXPORT_SYMBOL(sh_bios_gdb_detach);
 
 void sh_bios_get_node_addr (unsigned char *node_addr)
 {
diff --git a/arch/sh/kernel/sh_ksyms.c b/arch/sh/kernel/sh_ksyms.c
index c968dcf..37aef0a 100644
--- a/arch/sh/kernel/sh_ksyms.c
+++ b/arch/sh/kernel/sh_ksyms.c
@@ -63,10 +63,43 @@
 /* These symbols are generated by the compiler itself */
 DECLARE_EXPORT(__udivsi3);
 DECLARE_EXPORT(__sdivsi3);
+DECLARE_EXPORT(__ashrsi3);
+DECLARE_EXPORT(__ashlsi3);
 DECLARE_EXPORT(__ashrdi3);
 DECLARE_EXPORT(__ashldi3);
+DECLARE_EXPORT(__ashiftrt_r4_6);
+DECLARE_EXPORT(__ashiftrt_r4_7);
+DECLARE_EXPORT(__ashiftrt_r4_8);
+DECLARE_EXPORT(__ashiftrt_r4_9);
+DECLARE_EXPORT(__ashiftrt_r4_10);
+DECLARE_EXPORT(__ashiftrt_r4_11);
+DECLARE_EXPORT(__ashiftrt_r4_12);
+DECLARE_EXPORT(__ashiftrt_r4_13);
+DECLARE_EXPORT(__ashiftrt_r4_14);
+DECLARE_EXPORT(__ashiftrt_r4_15);
+DECLARE_EXPORT(__ashiftrt_r4_20);
+DECLARE_EXPORT(__ashiftrt_r4_21);
+DECLARE_EXPORT(__ashiftrt_r4_22);
+DECLARE_EXPORT(__ashiftrt_r4_23);
+DECLARE_EXPORT(__ashiftrt_r4_24);
+DECLARE_EXPORT(__ashiftrt_r4_27);
+DECLARE_EXPORT(__ashiftrt_r4_30);
+DECLARE_EXPORT(__lshrsi3);
 DECLARE_EXPORT(__lshrdi3);
+DECLARE_EXPORT(__movstrSI8);
+DECLARE_EXPORT(__movstrSI12);
 DECLARE_EXPORT(__movstrSI16);
+DECLARE_EXPORT(__movstrSI20);
+DECLARE_EXPORT(__movstrSI24);
+DECLARE_EXPORT(__movstrSI28);
+DECLARE_EXPORT(__movstrSI32);
+DECLARE_EXPORT(__movstrSI36);
+DECLARE_EXPORT(__movstrSI40);
+DECLARE_EXPORT(__movstrSI44);
+DECLARE_EXPORT(__movstrSI48);
+DECLARE_EXPORT(__movstrSI52);
+DECLARE_EXPORT(__movstrSI56);
+DECLARE_EXPORT(__movstrSI60);
 #if __GNUC__ == 4
 DECLARE_EXPORT(__movmem);
 #else
@@ -115,7 +148,9 @@
 #endif
 
 EXPORT_SYMBOL(csum_partial);
+EXPORT_SYMBOL(csum_partial_copy_generic);
 #ifdef CONFIG_IPV6
 EXPORT_SYMBOL(csum_ipv6_magic);
 #endif
 EXPORT_SYMBOL(clear_page);
+EXPORT_SYMBOL(__clear_user);
diff --git a/arch/sh/kernel/syscalls.S b/arch/sh/kernel/syscalls.S
index ff5656e..91fb702 100644
--- a/arch/sh/kernel/syscalls.S
+++ b/arch/sh/kernel/syscalls.S
@@ -358,3 +358,4 @@
 	.long sys_signalfd
 	.long sys_timerfd
 	.long sys_eventfd
+	.long sys_fallocate
diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S
index 5ba2161..9cb95af 100644
--- a/arch/sh/kernel/vmlinux.lds.S
+++ b/arch/sh/kernel/vmlinux.lds.S
@@ -22,6 +22,7 @@
 	*(.empty_zero_page)
 	} = 0
   .text : {
+  	*(.text.head)
 	TEXT_TEXT
 	SCHED_TEXT
 	LOCK_TEXT
diff --git a/arch/sh/mm/Kconfig b/arch/sh/mm/Kconfig
index 28d79a4..70da1c8 100644
--- a/arch/sh/mm/Kconfig
+++ b/arch/sh/mm/Kconfig
@@ -120,14 +120,14 @@
 config CPU_SUBTYPE_SH7750
 	bool "Support SH7750 processor"
 	select CPU_SH4
-	select CPU_HAS_IPR_IRQ
+	select CPU_HAS_INTC_IRQ
 	help
 	  Select SH7750 if you have a 200 Mhz SH-4 HD6417750 CPU.
 
 config CPU_SUBTYPE_SH7091
 	bool "Support SH7091 processor"
 	select CPU_SH4
-	select CPU_HAS_IPR_IRQ
+	select CPU_HAS_INTC_IRQ
 	help
 	  Select SH7091 if you have an SH-4 based Sega device (such as
 	  the Dreamcast, Naomi, and Naomi 2).
@@ -135,17 +135,17 @@
 config CPU_SUBTYPE_SH7750R
 	bool "Support SH7750R processor"
 	select CPU_SH4
-	select CPU_HAS_IPR_IRQ
+	select CPU_HAS_INTC_IRQ
 
 config CPU_SUBTYPE_SH7750S
 	bool "Support SH7750S processor"
 	select CPU_SH4
-	select CPU_HAS_IPR_IRQ
+	select CPU_HAS_INTC_IRQ
 
 config CPU_SUBTYPE_SH7751
 	bool "Support SH7751 processor"
 	select CPU_SH4
-	select CPU_HAS_IPR_IRQ
+	select CPU_HAS_INTC_IRQ
 	help
 	  Select SH7751 if you have a 166 Mhz SH-4 HD6417751 CPU,
 	  or if you have a HD6417751R CPU.
@@ -153,7 +153,7 @@
 config CPU_SUBTYPE_SH7751R
 	bool "Support SH7751R processor"
 	select CPU_SH4
-	select CPU_HAS_IPR_IRQ
+	select CPU_HAS_INTC_IRQ
 
 config CPU_SUBTYPE_SH7760
 	bool "Support SH7760 processor"
@@ -189,7 +189,7 @@
 config CPU_SUBTYPE_SH7780
 	bool "Support SH7780 processor"
 	select CPU_SH4A
-	select CPU_HAS_INTC2_IRQ
+	select CPU_HAS_INTC_IRQ
 
 config CPU_SUBTYPE_SH7785
 	bool "Support SH7785 processor"
@@ -217,7 +217,7 @@
 	bool "Support SH7722 processor"
 	select CPU_SH4AL_DSP
 	select CPU_SHX2
-	select CPU_HAS_IPR_IRQ
+	select CPU_HAS_INTC_IRQ
 	select ARCH_SPARSEMEM_ENABLE
 	select SYS_SUPPORTS_NUMA
 
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
index 2f48ba3..ad5cc5f 100644
--- a/drivers/char/watchdog/Kconfig
+++ b/drivers/char/watchdog/Kconfig
@@ -602,7 +602,7 @@
 
 config SH_WDT
 	tristate "SuperH Watchdog"
-	depends on SUPERH
+	depends on SUPERH && (CPU_SH3 || CPU_SH4)
 	help
 	  This driver adds watchdog support for the integrated watchdog in the
 	  SuperH processors. If you have one of these processors and wish
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index cea401f..35f3466 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -394,7 +394,7 @@
 
 config RTC_DRV_SH
 	tristate "SuperH On-Chip RTC"
-	depends on RTC_CLASS && SUPERH
+	depends on RTC_CLASS && SUPERH && (CPU_SH3 || CPU_SH4)
 	help
 	  Say Y here to enable support for the on-chip RTC found in
 	  most SuperH processors.
diff --git a/include/asm-sh/clock.h b/include/asm-sh/clock.h
index 386d797..b550a27 100644
--- a/include/asm-sh/clock.h
+++ b/include/asm-sh/clock.h
@@ -14,6 +14,7 @@
 	void (*disable)(struct clk *clk);
 	void (*recalc)(struct clk *clk);
 	int (*set_rate)(struct clk *clk, unsigned long rate, int algo_id);
+	long (*round_rate)(struct clk *clk, unsigned long rate);
 };
 
 struct clk {
diff --git a/include/asm-sh/hw_irq.h b/include/asm-sh/hw_irq.h
index 4ca3f76..20d4295 100644
--- a/include/asm-sh/hw_irq.h
+++ b/include/asm-sh/hw_irq.h
@@ -1,6 +1,7 @@
 #ifndef __ASM_SH_HW_IRQ_H
 #define __ASM_SH_HW_IRQ_H
 
+#include <linux/init.h>
 #include <asm/atomic.h>
 
 extern atomic_t irq_err_count;
@@ -22,7 +23,6 @@
 };
 
 void register_intc2_controller(struct intc2_desc *);
-void init_IRQ_intc2(void);
 
 struct ipr_data {
 	unsigned char irq;
@@ -40,11 +40,82 @@
 };
 
 void register_ipr_controller(struct ipr_desc *);
-void init_IRQ_ipr(void);
 
 /*
  * Enable individual interrupt mode for external IPR IRQs.
  */
-void ipr_irq_enable_irlm(void);
+void __init ipr_irq_enable_irlm(void);
+
+typedef unsigned char intc_enum;
+
+struct intc_vect {
+	intc_enum enum_id;
+	unsigned short vect;
+};
+
+#define INTC_VECT(enum_id, vect) { enum_id, vect }
+
+struct intc_prio {
+	intc_enum enum_id;
+	unsigned char priority;
+};
+
+#define INTC_PRIO(enum_id, prio) { enum_id, prio }
+
+struct intc_group {
+	intc_enum enum_id;
+	intc_enum *enum_ids;
+};
+
+#define INTC_GROUP(enum_id, ids...) { enum_id, (intc_enum []) { ids, 0 } }
+
+struct intc_mask_reg {
+	unsigned long set_reg, clr_reg, reg_width;
+	intc_enum enum_ids[32];
+};
+
+struct intc_prio_reg {
+	unsigned long reg, reg_width, field_width;
+	intc_enum enum_ids[16];
+};
+
+struct intc_sense_reg {
+	unsigned long reg, reg_width, field_width;
+	intc_enum enum_ids[16];
+};
+
+struct intc_desc {
+	struct intc_vect *vectors;
+	unsigned int nr_vectors;
+	struct intc_group *groups;
+	unsigned int nr_groups;
+	struct intc_prio *priorities;
+	unsigned int nr_priorities;
+	struct intc_mask_reg *mask_regs;
+	unsigned int nr_mask_regs;
+	struct intc_prio_reg *prio_regs;
+	unsigned int nr_prio_regs;
+	struct intc_sense_reg *sense_regs;
+	unsigned int nr_sense_regs;
+	struct irq_chip chip;
+};
+
+#define _INTC_ARRAY(a) a, sizeof(a)/sizeof(*a)
+#define DECLARE_INTC_DESC(symbol, chipname, vectors, groups,		\
+	priorities, mask_regs, prio_regs, sense_regs)			\
+struct intc_desc symbol = {						\
+	_INTC_ARRAY(vectors), _INTC_ARRAY(groups),			\
+	_INTC_ARRAY(priorities),					\
+	_INTC_ARRAY(mask_regs), _INTC_ARRAY(prio_regs),			\
+	_INTC_ARRAY(sense_regs),					\
+	.chip.name = chipname,						\
+}
+
+void __init register_intc_controller(struct intc_desc *desc);
+
+void __init plat_irq_setup(void);
+
+enum { IRQ_MODE_IRQ, IRQ_MODE_IRL7654, IRQ_MODE_IRL3210 };
+void __init plat_irq_setup_pins(int mode);
 
 #endif /* __ASM_SH_HW_IRQ_H */
diff --git a/include/asm-sh/se7722.h b/include/asm-sh/se7722.h
index b3b31e4..e0e89fc 100644
--- a/include/asm-sh/se7722.h
+++ b/include/asm-sh/se7722.h
@@ -81,36 +81,32 @@
 /* IRQ */
 #define IRQ0_IRQ        32
 #define IRQ1_IRQ        33
-#define INTC_ICR0       0xA4140000UL
-#define INTC_ICR1       0xA414001CUL
-
-#define INTMSK0         0xa4140044
-#define INTMSKCLR0      0xa4140064
-#define INTC_INTPRI0    0xa4140010
 
 #define IRQ01_MODE      0xb1800000
 #define IRQ01_STS       0xb1800004
 #define IRQ01_MASK      0xb1800008
-#define EXT_BIT		(0x3fc0)        /* SH IRQ1 */
-#define MRSHPC_BIT0	(0x0004)        /* SH IRQ1 */
-#define MRSHPC_BIT1	(0x0008)        /* SH IRQ1 */
-#define MRSHPC_BIT2	(0x0010)        /* SH IRQ1 */
-#define MRSHPC_BIT3	(0x0020)        /* SH IRQ1 */
-#define SMC_BIT		(0x0002)        /* SH IRQ0 */
-#define USB_BIT		(0x0001)        /* SH IRQ0 */
 
-#define MRSHPC_IRQ3    	11
-#define MRSHPC_IRQ2    	12
-#define MRSHPC_IRQ1    	13
-#define MRSHPC_IRQ0    	14
-#define SMC_IRQ		10
-#define EXT_IRQ		5
-#define USB_IRQ		6
+/* Bits in IRQ01_* registers */
 
+#define SE7722_FPGA_IRQ_USB	0 /* IRQ0 */
+#define SE7722_FPGA_IRQ_SMC	1 /* IRQ0 */
+#define SE7722_FPGA_IRQ_MRSHPC0	2 /* IRQ1 */
+#define SE7722_FPGA_IRQ_MRSHPC1	3 /* IRQ1 */
+#define SE7722_FPGA_IRQ_MRSHPC2	4 /* IRQ1 */
+#define SE7722_FPGA_IRQ_MRSHPC3	5 /* IRQ1 */
+
+#define SE7722_FPGA_IRQ_NR	6
+#define SE7722_FPGA_IRQ_BASE	110
+
+#define MRSHPC_IRQ3    	(SE7722_FPGA_IRQ_BASE + SE7722_FPGA_IRQ_MRSHPC3)
+#define MRSHPC_IRQ2    	(SE7722_FPGA_IRQ_BASE + SE7722_FPGA_IRQ_MRSHPC2)
+#define MRSHPC_IRQ1    	(SE7722_FPGA_IRQ_BASE + SE7722_FPGA_IRQ_MRSHPC1)
+#define MRSHPC_IRQ0    	(SE7722_FPGA_IRQ_BASE + SE7722_FPGA_IRQ_MRSHPC0)
+#define SMC_IRQ		(SE7722_FPGA_IRQ_BASE + SE7722_FPGA_IRQ_SMC)
+#define USB_IRQ		(SE7722_FPGA_IRQ_BASE + SE7722_FPGA_IRQ_USB)
 
 /* arch/sh/boards/se/7722/irq.c */
 void init_se7722_IRQ(void);
-int se7722_irq_demux(int);
 
 #define __IO_PREFIX		se7722
 #include <asm/io_generic.h>
diff --git a/include/asm-sh/unistd.h b/include/asm-sh/unistd.h
index 77bcb09..b182b1c 100644
--- a/include/asm-sh/unistd.h
+++ b/include/asm-sh/unistd.h
@@ -332,8 +332,9 @@
 #define __NR_signalfd		321
 #define __NR_timerfd		322
 #define __NR_eventfd		323
+#define __NR_fallocate		324
 
-#define NR_syscalls 324
+#define NR_syscalls 325
 
 #ifdef __KERNEL__