Merge branches 'ftrace', 'gic', 'io', 'kexec', 'mod', 'sa11x0', 'sh' and 'versatile' into devel
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index d56d21c..9d26083 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -23,6 +23,7 @@
 	select PERF_USE_VMALLOC
 	select HAVE_REGS_AND_STACK_ACCESS_API
 	select HAVE_HW_BREAKPOINT if (PERF_EVENTS && (CPU_V6 || CPU_V7))
+	select HAVE_C_RECORDMCOUNT
 	help
 	  The ARM series is a line of low-power-consumption RISC chip designs
 	  licensed by ARM Ltd and targeted at embedded applications and
@@ -1164,7 +1165,7 @@
 	bool
 
 config PCI
-	bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB || ARCH_IXP4XX || ARCH_KS8695 || MACH_ARMCORE || ARCH_CNS3XXX
+	bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB || ARCH_IXP4XX || ARCH_KS8695 || MACH_ARMCORE || ARCH_CNS3XXX || SA1100_NANOENGINE
 	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
@@ -1175,6 +1176,12 @@
 	bool
 	depends on PCI
 
+config PCI_NANOENGINE
+	bool "BSE nanoEngine PCI support"
+	depends on SA1100_NANOENGINE
+	help
+	  Enable PCI on the BSE nanoEngine board.
+
 config PCI_SYSCALL
 	def_bool PCI
 
@@ -1650,6 +1657,19 @@
 	  Should the atags used to boot the kernel be exported in an "atags"
 	  file in procfs. Useful with kexec.
 
+config CRASH_DUMP
+	bool "Build kdump crash kernel (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	help
+	  Generate crash dump after being started by kexec. This should
+	  be normally only set in special crash dump kernels which are
+	  loaded in the main kernel with kexec-tools into a specially
+	  reserved region and then later executed after a crash by
+	  kdump/kexec. The crash dump kernel must be compiled to a
+	  memory address not used by the main kernel
+
+	  For more details see Documentation/kdump/kdump.txt
+
 config AUTO_ZRELADDR
 	bool "Auto calculation of the decompressed kernel image address"
 	depends on !ZBOOT_ROM && !ARCH_U300
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index 65a7c1c..0a8f748 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -45,6 +45,10 @@
 endif
 endif
 
+ifeq ($(CONFIG_ARCH_SHMOBILE),y)
+OBJS		+= head-shmobile.o
+endif
+
 #
 # We now have a PIC decompressor implementation.  Decompressors running
 # from RAM should not define ZTEXTADDR.  Decompressors running directly
diff --git a/arch/arm/boot/compressed/head-shmobile.S b/arch/arm/boot/compressed/head-shmobile.S
new file mode 100644
index 0000000..30973b7
--- /dev/null
+++ b/arch/arm/boot/compressed/head-shmobile.S
@@ -0,0 +1,53 @@
+/*
+ * The head-file for SH-Mobile ARM platforms
+ *
+ * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ * Simon Horman <horms@verge.net.au>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifdef CONFIG_ZBOOT_ROM
+
+	.section	".start", "ax"
+
+	/* load board-specific initialization code */
+#include <mach/zboot.h>
+
+	b	1f
+__atags:@ tag #1
+	.long	12			@ tag->hdr.size = tag_size(tag_core);
+	.long	0x54410001		@ tag->hdr.tag = ATAG_CORE;
+	.long   0			@ tag->u.core.flags = 0;
+	.long	0			@ tag->u.core.pagesize = 0;
+	.long	0			@ tag->u.core.rootdev = 0;
+	@ tag #2
+	.long	8			@ tag->hdr.size = tag_size(tag_mem32);
+	.long	0x54410002		@ tag->hdr.tag = ATAG_MEM;
+	.long	CONFIG_MEMORY_SIZE	@ tag->u.mem.size = CONFIG_MEMORY_SIZE;
+	.long	CONFIG_MEMORY_START	@ @ tag->u.mem.start = CONFIG_MEMORY_START;
+	@ tag #3
+	.long	0			@ tag->hdr.size = 0
+	.long	0			@ tag->hdr.tag = ATAG_NONE;
+1:
+
+	/* Set board ID necessary for boot */
+	ldr	r7, 1f				@ Set machine type register
+	adr	r8, __atags			@ Set atag register
+	b	2f
+
+1 :	.long MACH_TYPE
+2 :
+
+#endif /* CONFIG_ZBOOT_ROM */
diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile
index e6e8664..e7521bca 100644
--- a/arch/arm/common/Makefile
+++ b/arch/arm/common/Makefile
@@ -17,3 +17,4 @@
 obj-$(CONFIG_ARCH_IXP23XX)	+= uengine.o
 obj-$(CONFIG_PCI_HOST_ITE8152)  += it8152.o
 obj-$(CONFIG_COMMON_CLKDEV)	+= clkdev.o
+obj-$(CONFIG_ARM_TIMER_SP804)	+= timer-sp.o
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index e6388dc..0b89ef0 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -35,6 +35,9 @@
 
 static DEFINE_SPINLOCK(irq_controller_lock);
 
+/* Address of GIC 0 CPU interface */
+void __iomem *gic_cpu_base_addr __read_mostly;
+
 struct gic_chip_data {
 	unsigned int irq_offset;
 	void __iomem *dist_base;
@@ -45,7 +48,7 @@
 #define MAX_GIC_NR	1
 #endif
 
-static struct gic_chip_data gic_data[MAX_GIC_NR];
+static struct gic_chip_data gic_data[MAX_GIC_NR] __read_mostly;
 
 static inline void __iomem *gic_dist_base(unsigned int irq)
 {
@@ -213,21 +216,16 @@
 	set_irq_chained_handler(irq, gic_handle_cascade_irq);
 }
 
-void __init gic_dist_init(unsigned int gic_nr, void __iomem *base,
-			  unsigned int irq_start)
+static void __init gic_dist_init(struct gic_chip_data *gic,
+	unsigned int irq_start)
 {
 	unsigned int gic_irqs, irq_limit, i;
+	void __iomem *base = gic->dist_base;
 	u32 cpumask = 1 << smp_processor_id();
 
-	if (gic_nr >= MAX_GIC_NR)
-		BUG();
-
 	cpumask |= cpumask << 8;
 	cpumask |= cpumask << 16;
 
-	gic_data[gic_nr].dist_base = base;
-	gic_data[gic_nr].irq_offset = (irq_start - 1) & ~31;
-
 	writel(0, base + GIC_DIST_CTRL);
 
 	/*
@@ -267,7 +265,7 @@
 	/*
 	 * Limit number of interrupts registered to the platform maximum
 	 */
-	irq_limit = gic_data[gic_nr].irq_offset + gic_irqs;
+	irq_limit = gic->irq_offset + gic_irqs;
 	if (WARN_ON(irq_limit > NR_IRQS))
 		irq_limit = NR_IRQS;
 
@@ -276,7 +274,7 @@
 	 */
 	for (i = irq_start; i < irq_limit; i++) {
 		set_irq_chip(i, &gic_chip);
-		set_irq_chip_data(i, &gic_data[gic_nr]);
+		set_irq_chip_data(i, gic);
 		set_irq_handler(i, handle_level_irq);
 		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
 	}
@@ -284,19 +282,12 @@
 	writel(1, base + GIC_DIST_CTRL);
 }
 
-void __cpuinit gic_cpu_init(unsigned int gic_nr, void __iomem *base)
+static void __cpuinit gic_cpu_init(struct gic_chip_data *gic)
 {
-	void __iomem *dist_base;
+	void __iomem *dist_base = gic->dist_base;
+	void __iomem *base = gic->cpu_base;
 	int i;
 
-	if (gic_nr >= MAX_GIC_NR)
-		BUG();
-
-	dist_base = gic_data[gic_nr].dist_base;
-	BUG_ON(!dist_base);
-
-	gic_data[gic_nr].cpu_base = base;
-
 	/*
 	 * Deal with the banked PPI and SGI interrupts - disable all
 	 * PPI interrupts, ensure all SGI interrupts are enabled.
@@ -314,6 +305,42 @@
 	writel(1, base + GIC_CPU_CTRL);
 }
 
+void __init gic_init(unsigned int gic_nr, unsigned int irq_start,
+	void __iomem *dist_base, void __iomem *cpu_base)
+{
+	struct gic_chip_data *gic;
+
+	BUG_ON(gic_nr >= MAX_GIC_NR);
+
+	gic = &gic_data[gic_nr];
+	gic->dist_base = dist_base;
+	gic->cpu_base = cpu_base;
+	gic->irq_offset = (irq_start - 1) & ~31;
+
+	if (gic_nr == 0)
+		gic_cpu_base_addr = cpu_base;
+
+	gic_dist_init(gic, irq_start);
+	gic_cpu_init(gic);
+}
+
+void __cpuinit gic_secondary_init(unsigned int gic_nr)
+{
+	BUG_ON(gic_nr >= MAX_GIC_NR);
+
+	gic_cpu_init(&gic_data[gic_nr]);
+}
+
+void __cpuinit gic_enable_ppi(unsigned int irq)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	irq_to_desc(irq)->status |= IRQ_NOPROBE;
+	gic_unmask_irq(irq);
+	local_irq_restore(flags);
+}
+
 #ifdef CONFIG_SMP
 void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
 {
diff --git a/arch/arm/plat-versatile/timer-sp.c b/arch/arm/common/timer-sp.c
similarity index 97%
rename from arch/arm/plat-versatile/timer-sp.c
rename to arch/arm/common/timer-sp.c
index fb0d1c2..4740313 100644
--- a/arch/arm/plat-versatile/timer-sp.c
+++ b/arch/arm/common/timer-sp.c
@@ -1,5 +1,5 @@
 /*
- *  linux/arch/arm/plat-versatile/timer-sp.c
+ *  linux/arch/arm/common/timer-sp.c
  *
  *  Copyright (C) 1999 - 2003 ARM Limited
  *  Copyright (C) 2000 Deep Blue Solutions Ltd
@@ -26,8 +26,6 @@
 
 #include <asm/hardware/arm_timer.h>
 
-#include <plat/timer-sp.h>
-
 /*
  * These timers are currently always setup to be clocked at 1MHz.
  */
diff --git a/arch/arm/include/asm/elf.h b/arch/arm/include/asm/elf.h
index 8bb66bc..c3cd875 100644
--- a/arch/arm/include/asm/elf.h
+++ b/arch/arm/include/asm/elf.h
@@ -99,6 +99,8 @@
 extern int elf_check_arch(const struct elf32_hdr *);
 #define elf_check_arch elf_check_arch
 
+#define vmcore_elf64_check_arch(x) (0)
+
 extern int arm_elf_read_implies_exec(const struct elf32_hdr *, int);
 #define elf_read_implies_exec(ex,stk) arm_elf_read_implies_exec(&(ex), stk)
 
diff --git a/arch/arm/include/asm/hardware/entry-macro-gic.S b/arch/arm/include/asm/hardware/entry-macro-gic.S
new file mode 100644
index 0000000..c115b82
--- /dev/null
+++ b/arch/arm/include/asm/hardware/entry-macro-gic.S
@@ -0,0 +1,75 @@
+/*
+ * arch/arm/include/asm/hardware/entry-macro-gic.S
+ *
+ * Low-level IRQ helper macros for GIC
+ *
+ * This file is licensed under  the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <asm/hardware/gic.h>
+
+#ifndef HAVE_GET_IRQNR_PREAMBLE
+	.macro	get_irqnr_preamble, base, tmp
+	ldr	\base, =gic_cpu_base_addr
+	ldr	\base, [\base]
+	.endm
+#endif
+
+/*
+ * The interrupt numbering scheme is defined in the
+ * interrupt controller spec.  To wit:
+ *
+ * Interrupts 0-15 are IPI
+ * 16-28 are reserved
+ * 29-31 are local.  We allow 30 to be used for the watchdog.
+ * 32-1020 are global
+ * 1021-1022 are reserved
+ * 1023 is "spurious" (no interrupt)
+ *
+ * For now, we ignore all local interrupts so only return an interrupt if it's
+ * between 30 and 1020.  The test_for_ipi routine below will pick up on IPIs.
+ *
+ * A simple read from the controller will tell us the number of the highest
+ * priority enabled interrupt.  We then just need to check whether it is in the
+ * valid range for an IRQ (30-1020 inclusive).
+ */
+
+	.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+
+	ldr     \irqstat, [\base, #GIC_CPU_INTACK]
+	/* bits 12-10 = src CPU, 9-0 = int # */
+
+	ldr	\tmp, =1021
+	bic     \irqnr, \irqstat, #0x1c00
+	cmp     \irqnr, #29
+	cmpcc	\irqnr, \irqnr
+	cmpne	\irqnr, \tmp
+	cmpcs	\irqnr, \irqnr
+	.endm
+
+/* We assume that irqstat (the raw value of the IRQ acknowledge
+ * register) is preserved from the macro above.
+ * If there is an IPI, we immediately signal end of interrupt on the
+ * controller, since this requires the original irqstat value which
+ * we won't easily be able to recreate later.
+ */
+
+	.macro test_for_ipi, irqnr, irqstat, base, tmp
+	bic	\irqnr, \irqstat, #0x1c00
+	cmp	\irqnr, #16
+	strcc	\irqstat, [\base, #GIC_CPU_EOI]
+	cmpcs	\irqnr, \irqnr
+	.endm
+
+/* As above, this assumes that irqstat and base are preserved.. */
+
+	.macro test_for_ltirq, irqnr, irqstat, base, tmp
+	bic	\irqnr, \irqstat, #0x1c00
+	mov 	\tmp, #0
+	cmp	\irqnr, #29
+	moveq	\tmp, #1
+	streq	\irqstat, [\base, #GIC_CPU_EOI]
+	cmp	\tmp, #0
+	.endm
diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
index 7f34333..84557d3 100644
--- a/arch/arm/include/asm/hardware/gic.h
+++ b/arch/arm/include/asm/hardware/gic.h
@@ -33,10 +33,13 @@
 #define GIC_DIST_SOFTINT		0xf00
 
 #ifndef __ASSEMBLY__
-void gic_dist_init(unsigned int gic_nr, void __iomem *base, unsigned int irq_start);
-void gic_cpu_init(unsigned int gic_nr, void __iomem *base);
+extern void __iomem *gic_cpu_base_addr;
+
+void gic_init(unsigned int, unsigned int, void __iomem *, void __iomem *);
+void gic_secondary_init(unsigned int);
 void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
 void gic_raise_softirq(const struct cpumask *mask, unsigned int irq);
+void gic_enable_ppi(unsigned int);
 #endif
 
 #endif
diff --git a/arch/arm/plat-versatile/include/plat/timer-sp.h b/arch/arm/include/asm/hardware/timer-sp.h
similarity index 100%
rename from arch/arm/plat-versatile/include/plat/timer-sp.h
rename to arch/arm/include/asm/hardware/timer-sp.h
diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index 815efa2..20e0f7c 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -241,18 +241,15 @@
  *
  */
 #ifndef __arch_ioremap
-#define ioremap(cookie,size)		__arm_ioremap(cookie, size, MT_DEVICE)
-#define ioremap_nocache(cookie,size)	__arm_ioremap(cookie, size, MT_DEVICE)
-#define ioremap_cached(cookie,size)	__arm_ioremap(cookie, size, MT_DEVICE_CACHED)
-#define ioremap_wc(cookie,size)		__arm_ioremap(cookie, size, MT_DEVICE_WC)
-#define iounmap(cookie)			__iounmap(cookie)
-#else
+#define __arch_ioremap			__arm_ioremap
+#define __arch_iounmap			__iounmap
+#endif
+
 #define ioremap(cookie,size)		__arch_ioremap((cookie), (size), MT_DEVICE)
 #define ioremap_nocache(cookie,size)	__arch_ioremap((cookie), (size), MT_DEVICE)
 #define ioremap_cached(cookie,size)	__arch_ioremap((cookie), (size), MT_DEVICE_CACHED)
 #define ioremap_wc(cookie,size)		__arch_ioremap((cookie), (size), MT_DEVICE_WC)
-#define iounmap(cookie)			__arch_iounmap(cookie)
-#endif
+#define iounmap				__arch_iounmap
 
 /*
  * io{read,write}{8,16,32} macros
diff --git a/arch/arm/include/asm/kexec.h b/arch/arm/include/asm/kexec.h
index 8ec9ef5..c0094d8 100644
--- a/arch/arm/include/asm/kexec.h
+++ b/arch/arm/include/asm/kexec.h
@@ -33,10 +33,20 @@
 	if (oldregs) {
 		memcpy(newregs, oldregs, sizeof(*newregs));
 	} else {
-		__asm__ __volatile__ ("stmia %0, {r0 - r15}"
-				      : : "r" (&newregs->ARM_r0));
-		__asm__ __volatile__ ("mrs %0, cpsr"
-				      : "=r" (newregs->ARM_cpsr));
+		__asm__ __volatile__ (
+			"stmia	%[regs_base], {r0-r12}\n\t"
+			"mov	%[_ARM_sp], sp\n\t"
+			"str	lr, %[_ARM_lr]\n\t"
+			"adr	%[_ARM_pc], 1f\n\t"
+			"mrs	%[_ARM_cpsr], cpsr\n\t"
+		"1:"
+			: [_ARM_pc] "=r" (newregs->ARM_pc),
+			  [_ARM_cpsr] "=r" (newregs->ARM_cpsr),
+			  [_ARM_sp] "=r" (newregs->ARM_sp),
+			  [_ARM_lr] "=o" (newregs->ARM_lr)
+			: [regs_base] "r" (&newregs->ARM_r0)
+			: "memory"
+		);
 	}
 }
 
diff --git a/arch/arm/include/asm/module.h b/arch/arm/include/asm/module.h
index cbb0bc2..12c8e68 100644
--- a/arch/arm/include/asm/module.h
+++ b/arch/arm/include/asm/module.h
@@ -8,11 +8,6 @@
 struct unwind_table;
 
 #ifdef CONFIG_ARM_UNWIND
-struct arm_unwind_mapping {
-	Elf_Shdr *unw_sec;
-	Elf_Shdr *sec_text;
-	struct unwind_table *unwind;
-};
 enum {
 	ARM_SEC_INIT,
 	ARM_SEC_DEVINIT,
@@ -21,14 +16,14 @@
 	ARM_SEC_DEVEXIT,
 	ARM_SEC_MAX,
 };
-struct mod_arch_specific {
-	struct arm_unwind_mapping map[ARM_SEC_MAX];
-};
-#else
-struct mod_arch_specific {
-};
 #endif
 
+struct mod_arch_specific {
+#ifdef CONFIG_ARM_UNWIND
+	struct unwind_table *unwind[ARM_SEC_MAX];
+#endif
+};
+
 /*
  * Include the ARM architecture version.
  */
diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c
index 3a8fd514..30ead13 100644
--- a/arch/arm/kernel/machine_kexec.c
+++ b/arch/arm/kernel/machine_kexec.c
@@ -23,6 +23,8 @@
 extern unsigned long kexec_mach_type;
 extern unsigned long kexec_boot_atags;
 
+static atomic_t waiting_for_crash_ipi;
+
 /*
  * Provide a dummy crash_notes definition while crash dump arrives to arm.
  * This prevents breakage of crash_notes attribute in kernel/ksysfs.c.
@@ -37,9 +39,37 @@
 {
 }
 
+void machine_crash_nonpanic_core(void *unused)
+{
+	struct pt_regs regs;
+
+	crash_setup_regs(&regs, NULL);
+	printk(KERN_DEBUG "CPU %u will stop doing anything useful since another CPU has crashed\n",
+	       smp_processor_id());
+	crash_save_cpu(&regs, smp_processor_id());
+	flush_cache_all();
+
+	atomic_dec(&waiting_for_crash_ipi);
+	while (1)
+		cpu_relax();
+}
+
 void machine_crash_shutdown(struct pt_regs *regs)
 {
+	unsigned long msecs;
+
 	local_irq_disable();
+
+	atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
+	smp_call_function(machine_crash_nonpanic_core, NULL, false);
+	msecs = 1000; /* Wait at most a second for the other cpus to stop */
+	while ((atomic_read(&waiting_for_crash_ipi) > 0) && msecs) {
+		mdelay(1);
+		msecs--;
+	}
+	if (atomic_read(&waiting_for_crash_ipi) > 0)
+		printk(KERN_WARNING "Non-crashing CPUs did not react to IPI\n");
+
 	crash_save_cpu(regs, smp_processor_id());
 
 	printk(KERN_INFO "Loading crashdump kernel...\n");
diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c
index d9bd786..0c1bb68 100644
--- a/arch/arm/kernel/module.c
+++ b/arch/arm/kernel/module.c
@@ -67,35 +67,6 @@
 			      char *secstrings,
 			      struct module *mod)
 {
-#ifdef CONFIG_ARM_UNWIND
-	Elf_Shdr *s, *sechdrs_end = sechdrs + hdr->e_shnum;
-	struct arm_unwind_mapping *maps = mod->arch.map;
-
-	for (s = sechdrs; s < sechdrs_end; s++) {
-		char const *secname = secstrings + s->sh_name;
-
-		if (strcmp(".ARM.exidx.init.text", secname) == 0)
-			maps[ARM_SEC_INIT].unw_sec = s;
-		else if (strcmp(".ARM.exidx.devinit.text", secname) == 0)
-			maps[ARM_SEC_DEVINIT].unw_sec = s;
-		else if (strcmp(".ARM.exidx", secname) == 0)
-			maps[ARM_SEC_CORE].unw_sec = s;
-		else if (strcmp(".ARM.exidx.exit.text", secname) == 0)
-			maps[ARM_SEC_EXIT].unw_sec = s;
-		else if (strcmp(".ARM.exidx.devexit.text", secname) == 0)
-			maps[ARM_SEC_DEVEXIT].unw_sec = s;
-		else if (strcmp(".init.text", secname) == 0)
-			maps[ARM_SEC_INIT].sec_text = s;
-		else if (strcmp(".devinit.text", secname) == 0)
-			maps[ARM_SEC_DEVINIT].sec_text = s;
-		else if (strcmp(".text", secname) == 0)
-			maps[ARM_SEC_CORE].sec_text = s;
-		else if (strcmp(".exit.text", secname) == 0)
-			maps[ARM_SEC_EXIT].sec_text = s;
-		else if (strcmp(".devexit.text", secname) == 0)
-			maps[ARM_SEC_DEVEXIT].sec_text = s;
-	}
-#endif
 	return 0;
 }
 
@@ -300,41 +271,69 @@
 	return -ENOEXEC;
 }
 
+struct mod_unwind_map {
+	const Elf_Shdr *unw_sec;
+	const Elf_Shdr *txt_sec;
+};
+
+int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs,
+		    struct module *mod)
+{
 #ifdef CONFIG_ARM_UNWIND
-static void register_unwind_tables(struct module *mod)
-{
+	const char *secstrs = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
+	const Elf_Shdr *s, *sechdrs_end = sechdrs + hdr->e_shnum;
+	struct mod_unwind_map maps[ARM_SEC_MAX];
 	int i;
-	for (i = 0; i < ARM_SEC_MAX; ++i) {
-		struct arm_unwind_mapping *map = &mod->arch.map[i];
-		if (map->unw_sec && map->sec_text)
-			map->unwind = unwind_table_add(map->unw_sec->sh_addr,
-						       map->unw_sec->sh_size,
-						       map->sec_text->sh_addr,
-						       map->sec_text->sh_size);
+
+	memset(maps, 0, sizeof(maps));
+
+	for (s = sechdrs; s < sechdrs_end; s++) {
+		const char *secname = secstrs + s->sh_name;
+
+		if (!(s->sh_flags & SHF_ALLOC))
+			continue;
+
+		if (strcmp(".ARM.exidx.init.text", secname) == 0)
+			maps[ARM_SEC_INIT].unw_sec = s;
+		else if (strcmp(".ARM.exidx.devinit.text", secname) == 0)
+			maps[ARM_SEC_DEVINIT].unw_sec = s;
+		else if (strcmp(".ARM.exidx", secname) == 0)
+			maps[ARM_SEC_CORE].unw_sec = s;
+		else if (strcmp(".ARM.exidx.exit.text", secname) == 0)
+			maps[ARM_SEC_EXIT].unw_sec = s;
+		else if (strcmp(".ARM.exidx.devexit.text", secname) == 0)
+			maps[ARM_SEC_DEVEXIT].unw_sec = s;
+		else if (strcmp(".init.text", secname) == 0)
+			maps[ARM_SEC_INIT].txt_sec = s;
+		else if (strcmp(".devinit.text", secname) == 0)
+			maps[ARM_SEC_DEVINIT].txt_sec = s;
+		else if (strcmp(".text", secname) == 0)
+			maps[ARM_SEC_CORE].txt_sec = s;
+		else if (strcmp(".exit.text", secname) == 0)
+			maps[ARM_SEC_EXIT].txt_sec = s;
+		else if (strcmp(".devexit.text", secname) == 0)
+			maps[ARM_SEC_DEVEXIT].txt_sec = s;
 	}
-}
 
-static void unregister_unwind_tables(struct module *mod)
-{
-	int i = ARM_SEC_MAX;
-	while (--i >= 0)
-		unwind_table_del(mod->arch.map[i].unwind);
-}
-#else
-static inline void register_unwind_tables(struct module *mod) { }
-static inline void unregister_unwind_tables(struct module *mod) { }
+	for (i = 0; i < ARM_SEC_MAX; i++)
+		if (maps[i].unw_sec && maps[i].txt_sec)
+			mod->arch.unwind[i] =
+				unwind_table_add(maps[i].unw_sec->sh_addr,
+					         maps[i].unw_sec->sh_size,
+					         maps[i].txt_sec->sh_addr,
+					         maps[i].txt_sec->sh_size);
 #endif
-
-int
-module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs,
-		struct module *module)
-{
-	register_unwind_tables(module);
 	return 0;
 }
 
 void
 module_arch_cleanup(struct module *mod)
 {
-	unregister_unwind_tables(mod);
+#ifdef CONFIG_ARM_UNWIND
+	int i;
+
+	for (i = 0; i < ARM_SEC_MAX; i++)
+		if (mod->arch.unwind[i])
+			unwind_table_del(mod->arch.unwind[i]);
+#endif
 }
diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c
index 35882fb..67f933e 100644
--- a/arch/arm/kernel/smp_twd.c
+++ b/arch/arm/kernel/smp_twd.c
@@ -127,8 +127,6 @@
  */
 void __cpuinit twd_timer_setup(struct clock_event_device *clk)
 {
-	unsigned long flags;
-
 	twd_calibrate_rate();
 
 	clk->name = "local_timer";
@@ -143,10 +141,7 @@
 	clk->min_delta_ns = clockevent_delta2ns(0xf, clk);
 
 	/* Make sure our local interrupt controller has this enabled */
-	local_irq_save(flags);
-	irq_to_desc(clk->irq)->status |= IRQ_NOPROBE;
-	get_irq_chip(clk->irq)->unmask(clk->irq);
-	local_irq_restore(flags);
+	gic_enable_ppi(clk->irq);
 
 	clockevents_register_device(clk);
 }
diff --git a/arch/arm/mach-cns3xxx/core.c b/arch/arm/mach-cns3xxx/core.c
index 9ca4d58..da30078 100644
--- a/arch/arm/mach-cns3xxx/core.c
+++ b/arch/arm/mach-cns3xxx/core.c
@@ -69,13 +69,10 @@
 }
 
 /* used by entry-macro.S */
-void __iomem *gic_cpu_base_addr;
-
 void __init cns3xxx_init_irq(void)
 {
-	gic_cpu_base_addr = __io(CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT);
-	gic_dist_init(0, __io(CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT), 29);
-	gic_cpu_init(0, gic_cpu_base_addr);
+	gic_init(0, 29, __io(CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT),
+		 __io(CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT));
 }
 
 void cns3xxx_power_off(void)
diff --git a/arch/arm/mach-cns3xxx/core.h b/arch/arm/mach-cns3xxx/core.h
index 6b33ec1..ef9e511 100644
--- a/arch/arm/mach-cns3xxx/core.h
+++ b/arch/arm/mach-cns3xxx/core.h
@@ -11,7 +11,6 @@
 #ifndef __CNS3XXX_CORE_H
 #define __CNS3XXX_CORE_H
 
-extern void __iomem *gic_cpu_base_addr;
 extern struct sys_timer cns3xxx_timer;
 
 void __init cns3xxx_map_io(void);
diff --git a/arch/arm/mach-cns3xxx/include/mach/entry-macro.S b/arch/arm/mach-cns3xxx/include/mach/entry-macro.S
index 5e1c554..6bd83ed 100644
--- a/arch/arm/mach-cns3xxx/include/mach/entry-macro.S
+++ b/arch/arm/mach-cns3xxx/include/mach/entry-macro.S
@@ -9,74 +9,10 @@
  */
 
 #include <mach/hardware.h>
-#include <asm/hardware/gic.h>
+#include <asm/hardware/entry-macro-gic.S>
 
 		.macro	disable_fiq
 		.endm
 
-		.macro  get_irqnr_preamble, base, tmp
-		ldr	\base, =gic_cpu_base_addr
-		ldr	\base, [\base]
-		.endm
-
 		.macro  arch_ret_to_user, tmp1, tmp2
 		.endm
-
-		/*
-		 * The interrupt numbering scheme is defined in the
-		 * interrupt controller spec.  To wit:
-		 *
-		 * Interrupts 0-15 are IPI
-		 * 16-28 are reserved
-		 * 29-31 are local.  We allow 30 to be used for the watchdog.
-		 * 32-1020 are global
-		 * 1021-1022 are reserved
-		 * 1023 is "spurious" (no interrupt)
-		 *
-		 * For now, we ignore all local interrupts so only return an interrupt if it's
-		 * between 30 and 1020.  The test_for_ipi routine below will pick up on IPIs.
-		 *
-		 * A simple read from the controller will tell us the number of the highest
-                 * priority enabled interrupt.  We then just need to check whether it is in the
-		 * valid range for an IRQ (30-1020 inclusive).
-		 */
-
-		.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-
-		ldr     \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 = src CPU, 9-0 = int # */
-
-		ldr	\tmp, =1021
-
-		bic     \irqnr, \irqstat, #0x1c00
-
-		cmp     \irqnr, #29
-		cmpcc	\irqnr, \irqnr
-		cmpne	\irqnr, \tmp
-		cmpcs	\irqnr, \irqnr
-
-		.endm
-
-		/* We assume that irqstat (the raw value of the IRQ acknowledge
-		 * register) is preserved from the macro above.
-		 * If there is an IPI, we immediately signal end of interrupt on the
-		 * controller, since this requires the original irqstat value which
-		 * we won't easily be able to recreate later.
-		 */
-
-		.macro test_for_ipi, irqnr, irqstat, base, tmp
-		bic	\irqnr, \irqstat, #0x1c00
-		cmp	\irqnr, #16
-		strcc	\irqstat, [\base, #GIC_CPU_EOI]
-		cmpcs	\irqnr, \irqnr
-		.endm
-
-		/* As above, this assumes that irqstat and base are preserved.. */
-
-		.macro test_for_ltirq, irqnr, irqstat, base, tmp
-		bic	\irqnr, \irqstat, #0x1c00
-		mov 	\tmp, #0
-		cmp	\irqnr, #29
-		moveq	\tmp, #1
-		streq	\irqstat, [\base, #GIC_CPU_EOI]
-		cmp	\tmp, #0
-		.endm
diff --git a/arch/arm/mach-davinci/include/mach/io.h b/arch/arm/mach-davinci/include/mach/io.h
index 62b0a90..d1b9549 100644
--- a/arch/arm/mach-davinci/include/mach/io.h
+++ b/arch/arm/mach-davinci/include/mach/io.h
@@ -22,8 +22,8 @@
 #define __mem_isa(a)		(a)
 
 #ifndef __ASSEMBLER__
-#define __arch_ioremap(p, s, t)	davinci_ioremap(p, s, t)
-#define __arch_iounmap(v)	davinci_iounmap(v)
+#define __arch_ioremap		davinci_ioremap
+#define __arch_iounmap		davinci_iounmap
 
 void __iomem *davinci_ioremap(unsigned long phys, size_t size,
 			      unsigned int type);
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c
index 6258c90..1713ecf 100644
--- a/arch/arm/mach-integrator/integrator_cp.c
+++ b/arch/arm/mach-integrator/integrator_cp.c
@@ -41,7 +41,7 @@
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
 
-#include <plat/timer-sp.h>
+#include <asm/hardware/timer-sp.h>
 
 #include "common.h"
 
diff --git a/arch/arm/mach-iop13xx/include/mach/io.h b/arch/arm/mach-iop13xx/include/mach/io.h
index a6e0f9e..dffb234 100644
--- a/arch/arm/mach-iop13xx/include/mach/io.h
+++ b/arch/arm/mach-iop13xx/include/mach/io.h
@@ -35,7 +35,7 @@
 extern size_t iop13xx_atue_mem_size;
 extern size_t iop13xx_atux_mem_size;
 
-#define __arch_ioremap(a, s, f) __iop13xx_ioremap(a, s, f)
-#define __arch_iounmap(a)	 __iop13xx_iounmap(a)
+#define __arch_ioremap	__iop13xx_ioremap
+#define __arch_iounmap	__iop13xx_iounmap
 
 #endif
diff --git a/arch/arm/mach-iop32x/include/mach/io.h b/arch/arm/mach-iop32x/include/mach/io.h
index 339e585..059c783 100644
--- a/arch/arm/mach-iop32x/include/mach/io.h
+++ b/arch/arm/mach-iop32x/include/mach/io.h
@@ -21,7 +21,7 @@
 #define __io(p)		((void __iomem *)IOP3XX_PCI_IO_PHYS_TO_VIRT(p))
 #define __mem_pci(a)		(a)
 
-#define __arch_ioremap(a, s, f) __iop3xx_ioremap(a, s, f)
-#define __arch_iounmap(a)	 __iop3xx_iounmap(a)
+#define __arch_ioremap	__iop3xx_ioremap
+#define __arch_iounmap	__iop3xx_iounmap
 
 #endif
diff --git a/arch/arm/mach-iop33x/include/mach/io.h b/arch/arm/mach-iop33x/include/mach/io.h
index e99a7ed..39e893e 100644
--- a/arch/arm/mach-iop33x/include/mach/io.h
+++ b/arch/arm/mach-iop33x/include/mach/io.h
@@ -21,7 +21,7 @@
 #define __io(p)		((void __iomem *)IOP3XX_PCI_IO_PHYS_TO_VIRT(p))
 #define __mem_pci(a)		(a)
 
-#define __arch_ioremap(a, s, f) __iop3xx_ioremap(a, s, f)
-#define __arch_iounmap(a)	 __iop3xx_iounmap(a)
+#define __arch_ioremap	__iop3xx_ioremap
+#define __arch_iounmap	__iop3xx_iounmap
 
 #endif
diff --git a/arch/arm/mach-ixp23xx/include/mach/io.h b/arch/arm/mach-ixp23xx/include/mach/io.h
index fd9ef8e..a1749d0 100644
--- a/arch/arm/mach-ixp23xx/include/mach/io.h
+++ b/arch/arm/mach-ixp23xx/include/mach/io.h
@@ -45,8 +45,8 @@
 	__iounmap(addr);
 }
 
-#define __arch_ioremap(a,s,f)	ixp23xx_ioremap(a,s,f)
-#define __arch_iounmap(a)	ixp23xx_iounmap(a)
+#define __arch_ioremap	ixp23xx_ioremap
+#define __arch_iounmap	ixp23xx_iounmap
 
 
 #endif
diff --git a/arch/arm/mach-ixp4xx/include/mach/io.h b/arch/arm/mach-ixp4xx/include/mach/io.h
index de274a1..57b5410 100644
--- a/arch/arm/mach-ixp4xx/include/mach/io.h
+++ b/arch/arm/mach-ixp4xx/include/mach/io.h
@@ -74,8 +74,8 @@
 		__iounmap(addr);
 }
 
-#define __arch_ioremap(a, s, f)		__indirect_ioremap(a, s, f)
-#define __arch_iounmap(a)		__indirect_iounmap(a)
+#define __arch_ioremap			__indirect_ioremap
+#define __arch_iounmap			__indirect_iounmap
 
 #define writeb(v, p)			__indirect_writeb(v, p)
 #define writew(v, p)			__indirect_writew(v, p)
diff --git a/arch/arm/mach-kirkwood/include/mach/io.h b/arch/arm/mach-kirkwood/include/mach/io.h
index 44e8be0..1aaddc3 100644
--- a/arch/arm/mach-kirkwood/include/mach/io.h
+++ b/arch/arm/mach-kirkwood/include/mach/io.h
@@ -42,8 +42,8 @@
 		__iounmap(addr);
 }
 
-#define __arch_ioremap(p, s, m)	__arch_ioremap(p, s, m)
-#define __arch_iounmap(a)	__arch_iounmap(a)
+#define __arch_ioremap		__arch_ioremap
+#define __arch_iounmap		__arch_iounmap
 #define __io(a)			__io(a)
 #define __mem_pci(a)		(a)
 
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 7486a68..9b5eb2b 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -28,8 +28,6 @@
 #include <mach/board.h>
 #include <mach/msm_iomap.h>
 
-void __iomem *gic_cpu_base_addr;
-
 unsigned long clk_get_max_axi_khz(void)
 {
 	return 0;
@@ -44,9 +42,8 @@
 {
 	unsigned int i;
 
-	gic_dist_init(0, MSM_QGIC_DIST_BASE, GIC_PPI_START);
-	gic_cpu_base_addr = (void *)MSM_QGIC_CPU_BASE;
-	gic_cpu_init(0, MSM_QGIC_CPU_BASE);
+	gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE,
+		 (void *)MSM_QGIC_CPU_BASE);
 
 	/* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */
 	writel(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
diff --git a/arch/arm/mach-omap2/include/mach/entry-macro.S b/arch/arm/mach-omap2/include/mach/entry-macro.S
index 06e64e1..d54c4f8 100644
--- a/arch/arm/mach-omap2/include/mach/entry-macro.S
+++ b/arch/arm/mach-omap2/include/mach/entry-macro.S
@@ -105,6 +105,35 @@
 9999:
 		.endm
 
+#ifdef CONFIG_SMP
+		/* We assume that irqstat (the raw value of the IRQ acknowledge
+		 * register) is preserved from the macro above.
+		 * If there is an IPI, we immediately signal end of interrupt
+		 * on the controller, since this requires the original irqstat
+		 * value which we won't easily be able to recreate later.
+		 */
+
+		.macro test_for_ipi, irqnr, irqstat, base, tmp
+		bic	\irqnr, \irqstat, #0x1c00
+		cmp	\irqnr, #16
+		it	cc
+		strcc	\irqstat, [\base, #GIC_CPU_EOI]
+		it	cs
+		cmpcs	\irqnr, \irqnr
+		.endm
+
+		/* As above, this assumes that irqstat and base are preserved */
+
+		.macro test_for_ltirq, irqnr, irqstat, base, tmp
+		bic	\irqnr, \irqstat, #0x1c00
+		mov 	\tmp, #0
+		cmp	\irqnr, #29
+		itt	eq
+		moveq	\tmp, #1
+		streq	\irqstat, [\base, #GIC_CPU_EOI]
+		cmp	\tmp, #0
+		.endm
+#endif	/* CONFIG_SMP */
 
 #else	/* MULTI_OMAP2 */
 
@@ -141,74 +170,16 @@
 
 
 #ifdef CONFIG_ARCH_OMAP4
+#define HAVE_GET_IRQNR_PREAMBLE
+#include <asm/hardware/entry-macro-gic.S>
 
 		.macro  get_irqnr_preamble, base, tmp
 		ldr     \base, =OMAP4_IRQ_BASE
 		.endm
 
-		/*
-		 * The interrupt numbering scheme is defined in the
-		 * interrupt controller spec.  To wit:
-		 *
-		 * Interrupts 0-15 are IPI
-		 * 16-28 are reserved
-		 * 29-31 are local.  We allow 30 to be used for the watchdog.
-		 * 32-1020 are global
-		 * 1021-1022 are reserved
-		 * 1023 is "spurious" (no interrupt)
-		 *
-		 * For now, we ignore all local interrupts so only return an
-		 * interrupt if it's between 30 and 1020.  The test_for_ipi
-		 * routine below will pick up on IPIs.
-		 * A simple read from the controller will tell us the number
-		 * of the highest priority enabled interrupt.
-		 * We then just need to check whether it is in the
-		 * valid range for an IRQ (30-1020 inclusive).
-		 */
-		.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-		ldr     \irqstat, [\base, #GIC_CPU_INTACK]
-
-		ldr     \tmp, =1021
-
-		bic     \irqnr, \irqstat, #0x1c00
-
-		cmp     \irqnr, #29
-		cmpcc   \irqnr, \irqnr
-		cmpne   \irqnr, \tmp
-		cmpcs   \irqnr, \irqnr
-		.endm
 #endif
+
 #endif	/* MULTI_OMAP2 */
 
-#ifdef CONFIG_SMP
-		/* We assume that irqstat (the raw value of the IRQ acknowledge
-		 * register) is preserved from the macro above.
-		 * If there is an IPI, we immediately signal end of interrupt
-		 * on the controller, since this requires the original irqstat
-		 * value which we won't easily be able to recreate later.
-		 */
-
-		.macro test_for_ipi, irqnr, irqstat, base, tmp
-		bic	\irqnr, \irqstat, #0x1c00
-		cmp	\irqnr, #16
-		it	cc
-		strcc	\irqstat, [\base, #GIC_CPU_EOI]
-		it	cs
-		cmpcs	\irqnr, \irqnr
-		.endm
-
-		/* As above, this assumes that irqstat and base are preserved */
-
-		.macro test_for_ltirq, irqnr, irqstat, base, tmp
-		bic	\irqnr, \irqstat, #0x1c00
-		mov 	\tmp, #0
-		cmp	\irqnr, #29
-		itt	eq
-		moveq	\tmp, #1
-		streq	\irqstat, [\base, #GIC_CPU_EOI]
-		cmp	\tmp, #0
-		.endm
-#endif	/* CONFIG_SMP */
-
 		.macro	irq_prio_table
 		.endm
diff --git a/arch/arm/mach-omap2/include/mach/omap4-common.h b/arch/arm/mach-omap2/include/mach/omap4-common.h
index 2744dfe..5b0270b 100644
--- a/arch/arm/mach-omap2/include/mach/omap4-common.h
+++ b/arch/arm/mach-omap2/include/mach/omap4-common.h
@@ -24,7 +24,6 @@
 extern void __iomem *l2cache_base;
 #endif
 
-extern void __iomem *gic_cpu_base_addr;
 extern void __iomem *gic_dist_base_addr;
 
 extern void __init gic_init_irq(void);
diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c
index 9e9f70e..9fbac2c 100644
--- a/arch/arm/mach-omap2/omap-smp.c
+++ b/arch/arm/mach-omap2/omap-smp.c
@@ -50,7 +50,7 @@
 	 * core (e.g. timer irq), then they will not have been enabled
 	 * for us: do so
 	 */
-	gic_cpu_init(0, gic_cpu_base_addr);
+	gic_secondary_init(0);
 
 	/*
 	 * Synchronise with the boot thread.
diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c
index 2f89555..666e852 100644
--- a/arch/arm/mach-omap2/omap4-common.c
+++ b/arch/arm/mach-omap2/omap4-common.c
@@ -26,21 +26,22 @@
 void __iomem *l2cache_base;
 #endif
 
-void __iomem *gic_cpu_base_addr;
 void __iomem *gic_dist_base_addr;
 
 
 void __init gic_init_irq(void)
 {
+	void __iomem *gic_cpu_base;
+
 	/* Static mapping, never released */
 	gic_dist_base_addr = ioremap(OMAP44XX_GIC_DIST_BASE, SZ_4K);
 	BUG_ON(!gic_dist_base_addr);
-	gic_dist_init(0, gic_dist_base_addr, 29);
 
 	/* Static mapping, never released */
-	gic_cpu_base_addr = ioremap(OMAP44XX_GIC_CPU_BASE, SZ_512);
-	BUG_ON(!gic_cpu_base_addr);
-	gic_cpu_init(0, gic_cpu_base_addr);
+	gic_cpu_base = ioremap(OMAP44XX_GIC_CPU_BASE, SZ_512);
+	BUG_ON(!gic_cpu_base);
+
+	gic_init(0, 29, gic_dist_base_addr, gic_cpu_base);
 }
 
 #ifdef CONFIG_CACHE_L2X0
diff --git a/arch/arm/mach-orion5x/include/mach/io.h b/arch/arm/mach-orion5x/include/mach/io.h
index c47b033..c519610 100644
--- a/arch/arm/mach-orion5x/include/mach/io.h
+++ b/arch/arm/mach-orion5x/include/mach/io.h
@@ -38,8 +38,8 @@
 		__iounmap(addr);
 }
 
-#define __arch_ioremap(p, s, m)	__arch_ioremap(p, s, m)
-#define __arch_iounmap(a)	__arch_iounmap(a)
+#define __arch_ioremap		__arch_ioremap
+#define __arch_iounmap		__arch_iounmap
 #define __io(a)			__typesafe_io(a)
 #define __mem_pci(a)		(a)
 
diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c
index 07c0815..14fbe50 100644
--- a/arch/arm/mach-realview/core.c
+++ b/arch/arm/mach-realview/core.c
@@ -50,13 +50,10 @@
 #include <mach/clkdev.h>
 #include <mach/platform.h>
 #include <mach/irqs.h>
-#include <plat/timer-sp.h>
+#include <asm/hardware/timer-sp.h>
 
 #include "core.h"
 
-/* used by entry-macro.S and platsmp.c */
-void __iomem *gic_cpu_base_addr;
-
 #ifdef CONFIG_ZONE_DMA
 /*
  * Adjust the zones if there are restrictions for DMA access.
diff --git a/arch/arm/mach-realview/core.h b/arch/arm/mach-realview/core.h
index 781bca6..693239d 100644
--- a/arch/arm/mach-realview/core.h
+++ b/arch/arm/mach-realview/core.h
@@ -53,7 +53,6 @@
 extern struct mmci_platform_data realview_mmc0_plat_data;
 extern struct mmci_platform_data realview_mmc1_plat_data;
 extern struct clcd_board clcd_plat_data;
-extern void __iomem *gic_cpu_base_addr;
 extern void __iomem *timer0_va_base;
 extern void __iomem *timer1_va_base;
 extern void __iomem *timer2_va_base;
diff --git a/arch/arm/mach-realview/include/mach/entry-macro.S b/arch/arm/mach-realview/include/mach/entry-macro.S
index 340a5c2..4071164 100644
--- a/arch/arm/mach-realview/include/mach/entry-macro.S
+++ b/arch/arm/mach-realview/include/mach/entry-macro.S
@@ -8,74 +8,11 @@
  * warranty of any kind, whether express or implied.
  */
 #include <mach/hardware.h>
-#include <asm/hardware/gic.h>
+#include <asm/hardware/entry-macro-gic.S>
 
 		.macro	disable_fiq
 		.endm
 
-		.macro  get_irqnr_preamble, base, tmp
-		ldr	\base, =gic_cpu_base_addr
-		ldr	\base, [\base]
-		.endm
-
 		.macro  arch_ret_to_user, tmp1, tmp2
 		.endm
 
-		/*
-		 * The interrupt numbering scheme is defined in the
-		 * interrupt controller spec.  To wit:
-		 *
-		 * Interrupts 0-15 are IPI
-		 * 16-28 are reserved
-		 * 29-31 are local.  We allow 30 to be used for the watchdog.
-		 * 32-1020 are global
-		 * 1021-1022 are reserved
-		 * 1023 is "spurious" (no interrupt)
-		 *
-		 * For now, we ignore all local interrupts so only return an interrupt if it's
-		 * between 30 and 1020.  The test_for_ipi routine below will pick up on IPIs.
-		 *
-		 * A simple read from the controller will tell us the number of the highest
-                 * priority enabled interrupt.  We then just need to check whether it is in the
-		 * valid range for an IRQ (30-1020 inclusive).
-		 */
-
-		.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-
-		ldr     \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 = src CPU, 9-0 = int # */
-
-		ldr	\tmp, =1021
-
-		bic     \irqnr, \irqstat, #0x1c00
-
-		cmp     \irqnr, #29
-		cmpcc	\irqnr, \irqnr
-		cmpne	\irqnr, \tmp
-		cmpcs	\irqnr, \irqnr
-
-		.endm
-
-		/* We assume that irqstat (the raw value of the IRQ acknowledge
-		 * register) is preserved from the macro above.
-		 * If there is an IPI, we immediately signal end of interrupt on the
-		 * controller, since this requires the original irqstat value which
-		 * we won't easily be able to recreate later.
-		 */
-
-		.macro test_for_ipi, irqnr, irqstat, base, tmp
-		bic	\irqnr, \irqstat, #0x1c00
-		cmp	\irqnr, #16
-		strcc	\irqstat, [\base, #GIC_CPU_EOI]
-		cmpcs	\irqnr, \irqnr
-		.endm
-
-		/* As above, this assumes that irqstat and base are preserved.. */
-
-		.macro test_for_ltirq, irqnr, irqstat, base, tmp
-		bic	\irqnr, \irqstat, #0x1c00
-		mov 	\tmp, #0
-		cmp	\irqnr, #29
-		moveq	\tmp, #1
-		streq	\irqstat, [\base, #GIC_CPU_EOI]
-		cmp	\tmp, #0
-		.endm
diff --git a/arch/arm/mach-realview/platsmp.c b/arch/arm/mach-realview/platsmp.c
index 0092658..6da8a2e 100644
--- a/arch/arm/mach-realview/platsmp.c
+++ b/arch/arm/mach-realview/platsmp.c
@@ -69,7 +69,7 @@
 	 * core (e.g. timer irq), then they will not have been enabled
 	 * for us: do so
 	 */
-	gic_cpu_init(0, gic_cpu_base_addr);
+	gic_secondary_init(0);
 
 	/*
 	 * let the primary processor know we're out of the
diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c
index f269710..6ef5c5e 100644
--- a/arch/arm/mach-realview/realview_eb.c
+++ b/arch/arm/mach-realview/realview_eb.c
@@ -364,21 +364,19 @@
 		writel(0x00000000, __io_address(REALVIEW_SYS_LOCK));
 
 		/* core tile GIC, primary */
-		gic_cpu_base_addr = __io_address(REALVIEW_EB11MP_GIC_CPU_BASE);
-		gic_dist_init(0, __io_address(REALVIEW_EB11MP_GIC_DIST_BASE), 29);
-		gic_cpu_init(0, gic_cpu_base_addr);
+		gic_init(0, 29, __io_address(REALVIEW_EB11MP_GIC_DIST_BASE),
+			 __io_address(REALVIEW_EB11MP_GIC_CPU_BASE));
 
 #ifndef CONFIG_REALVIEW_EB_ARM11MP_REVB
 		/* board GIC, secondary */
-		gic_dist_init(1, __io_address(REALVIEW_EB_GIC_DIST_BASE), 64);
-		gic_cpu_init(1, __io_address(REALVIEW_EB_GIC_CPU_BASE));
+		gic_init(1, 64, __io_address(REALVIEW_EB_GIC_DIST_BASE),
+			 __io_address(REALVIEW_EB_GIC_CPU_BASE));
 		gic_cascade_irq(1, IRQ_EB11MP_EB_IRQ1);
 #endif
 	} else {
 		/* board GIC, primary */
-		gic_cpu_base_addr = __io_address(REALVIEW_EB_GIC_CPU_BASE);
-		gic_dist_init(0, __io_address(REALVIEW_EB_GIC_DIST_BASE), 29);
-		gic_cpu_init(0, gic_cpu_base_addr);
+		gic_init(0, 29, __io_address(REALVIEW_EB_GIC_DIST_BASE),
+			 __io_address(REALVIEW_EB_GIC_CPU_BASE));
 	}
 }
 
diff --git a/arch/arm/mach-realview/realview_pb1176.c b/arch/arm/mach-realview/realview_pb1176.c
index a412561..cbdc97a 100644
--- a/arch/arm/mach-realview/realview_pb1176.c
+++ b/arch/arm/mach-realview/realview_pb1176.c
@@ -304,13 +304,14 @@
 static void __init gic_init_irq(void)
 {
 	/* ARM1176 DevChip GIC, primary */
-	gic_cpu_base_addr = __io_address(REALVIEW_DC1176_GIC_CPU_BASE);
-	gic_dist_init(0, __io_address(REALVIEW_DC1176_GIC_DIST_BASE), IRQ_DC1176_GIC_START);
-	gic_cpu_init(0, gic_cpu_base_addr);
+	gic_init(0, IRQ_DC1176_GIC_START,
+		 __io_address(REALVIEW_DC1176_GIC_DIST_BASE),
+		 __io_address(REALVIEW_DC1176_GIC_CPU_BASE));
 
 	/* board GIC, secondary */
-	gic_dist_init(1, __io_address(REALVIEW_PB1176_GIC_DIST_BASE), IRQ_PB1176_GIC_START);
-	gic_cpu_init(1, __io_address(REALVIEW_PB1176_GIC_CPU_BASE));
+	gic_init(1, IRQ_PB1176_GIC_START,
+		 __io_address(REALVIEW_PB1176_GIC_DIST_BASE),
+		 __io_address(REALVIEW_PB1176_GIC_CPU_BASE));
 	gic_cascade_irq(1, IRQ_DC1176_PB_IRQ1);
 }
 
diff --git a/arch/arm/mach-realview/realview_pb11mp.c b/arch/arm/mach-realview/realview_pb11mp.c
index 117b95b..8e8ab7d 100644
--- a/arch/arm/mach-realview/realview_pb11mp.c
+++ b/arch/arm/mach-realview/realview_pb11mp.c
@@ -309,13 +309,13 @@
 	writel(0x00000000, __io_address(REALVIEW_SYS_LOCK));
 
 	/* ARM11MPCore test chip GIC, primary */
-	gic_cpu_base_addr = __io_address(REALVIEW_TC11MP_GIC_CPU_BASE);
-	gic_dist_init(0, __io_address(REALVIEW_TC11MP_GIC_DIST_BASE), 29);
-	gic_cpu_init(0, gic_cpu_base_addr);
+	gic_init(0, 29, __io_address(REALVIEW_TC11MP_GIC_DIST_BASE),
+		 __io_address(REALVIEW_TC11MP_GIC_CPU_BASE));
 
 	/* board GIC, secondary */
-	gic_dist_init(1, __io_address(REALVIEW_PB11MP_GIC_DIST_BASE), IRQ_PB11MP_GIC_START);
-	gic_cpu_init(1, __io_address(REALVIEW_PB11MP_GIC_CPU_BASE));
+	gic_init(1, IRQ_PB11MP_GIC_START,
+		 __io_address(REALVIEW_PB11MP_GIC_DIST_BASE),
+		 __io_address(REALVIEW_PB11MP_GIC_CPU_BASE));
 	gic_cascade_irq(1, IRQ_TC11MP_PB_IRQ1);
 }
 
diff --git a/arch/arm/mach-realview/realview_pba8.c b/arch/arm/mach-realview/realview_pba8.c
index 929b8dc..841118e 100644
--- a/arch/arm/mach-realview/realview_pba8.c
+++ b/arch/arm/mach-realview/realview_pba8.c
@@ -273,9 +273,9 @@
 static void __init gic_init_irq(void)
 {
 	/* ARM PB-A8 on-board GIC */
-	gic_cpu_base_addr = __io_address(REALVIEW_PBA8_GIC_CPU_BASE);
-	gic_dist_init(0, __io_address(REALVIEW_PBA8_GIC_DIST_BASE), IRQ_PBA8_GIC_START);
-	gic_cpu_init(0, __io_address(REALVIEW_PBA8_GIC_CPU_BASE));
+	gic_init(0, IRQ_PBA8_GIC_START,
+		 __io_address(REALVIEW_PBA8_GIC_DIST_BASE),
+		 __io_address(REALVIEW_PBA8_GIC_CPU_BASE));
 }
 
 static void __init realview_pba8_timer_init(void)
diff --git a/arch/arm/mach-realview/realview_pbx.c b/arch/arm/mach-realview/realview_pbx.c
index b9f9e20..02b755b 100644
--- a/arch/arm/mach-realview/realview_pbx.c
+++ b/arch/arm/mach-realview/realview_pbx.c
@@ -313,15 +313,12 @@
 {
 	/* ARM PBX on-board GIC */
 	if (core_tile_pbx11mp() || core_tile_pbxa9mp()) {
-		gic_cpu_base_addr = __io_address(REALVIEW_PBX_TILE_GIC_CPU_BASE);
-		gic_dist_init(0, __io_address(REALVIEW_PBX_TILE_GIC_DIST_BASE),
-			      29);
-		gic_cpu_init(0, __io_address(REALVIEW_PBX_TILE_GIC_CPU_BASE));
+		gic_init(0, 29, __io_address(REALVIEW_PBX_TILE_GIC_DIST_BASE),
+			 __io_address(REALVIEW_PBX_TILE_GIC_CPU_BASE));
 	} else {
-		gic_cpu_base_addr = __io_address(REALVIEW_PBX_GIC_CPU_BASE);
-		gic_dist_init(0, __io_address(REALVIEW_PBX_GIC_DIST_BASE),
-			      IRQ_PBX_GIC_START);
-		gic_cpu_init(0, __io_address(REALVIEW_PBX_GIC_CPU_BASE));
+		gic_init(0, IRQ_PBX_GIC_START,
+			 __io_address(REALVIEW_PBX_GIC_DIST_BASE),
+			 __io_address(REALVIEW_PBX_GIC_CPU_BASE));
 	}
 }
 
diff --git a/arch/arm/mach-s5pv310/cpu.c b/arch/arm/mach-s5pv310/cpu.c
index 82ce4aa..72ab289 100644
--- a/arch/arm/mach-s5pv310/cpu.c
+++ b/arch/arm/mach-s5pv310/cpu.c
@@ -24,8 +24,6 @@
 
 #include <mach/regs-irq.h>
 
-void __iomem *gic_cpu_base_addr;
-
 extern int combiner_init(unsigned int combiner_nr, void __iomem *base,
 			 unsigned int irq_start);
 extern void combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq);
@@ -122,9 +120,7 @@
 {
 	int irq;
 
-	gic_cpu_base_addr = S5P_VA_GIC_CPU;
-	gic_dist_init(0, S5P_VA_GIC_DIST, IRQ_LOCALTIMER);
-	gic_cpu_init(0, S5P_VA_GIC_CPU);
+	gic_init(0, IRQ_LOCALTIMER, S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
 
 	for (irq = 0; irq < MAX_COMBINER_NR; irq++) {
 		combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq),
diff --git a/arch/arm/mach-s5pv310/include/mach/smp.h b/arch/arm/mach-s5pv310/include/mach/smp.h
index b7ec252..e1cc6a2 100644
--- a/arch/arm/mach-s5pv310/include/mach/smp.h
+++ b/arch/arm/mach-s5pv310/include/mach/smp.h
@@ -9,8 +9,6 @@
 #include <asm/hardware/gic.h>
 #include <asm/smp_mpidr.h>
 
-extern void __iomem *gic_cpu_base_addr;
-
 /*
  * We use IRQ1 as the IPI
  */
diff --git a/arch/arm/mach-s5pv310/platsmp.c b/arch/arm/mach-s5pv310/platsmp.c
index d357c19..15929c1 100644
--- a/arch/arm/mach-s5pv310/platsmp.c
+++ b/arch/arm/mach-s5pv310/platsmp.c
@@ -54,7 +54,7 @@
 	 * core (e.g. timer irq), then they will not have been enabled
 	 * for us: do so
 	 */
-	gic_cpu_init(0, gic_cpu_base_addr);
+	gic_secondary_init(0);
 
 	/*
 	 * let the primary processor know we're out of the
diff --git a/arch/arm/mach-sa1100/Kconfig b/arch/arm/mach-sa1100/Kconfig
index 5da8c35..42625e4 100644
--- a/arch/arm/mach-sa1100/Kconfig
+++ b/arch/arm/mach-sa1100/Kconfig
@@ -118,6 +118,16 @@
 	  (also known as the LART).  See <http://www.lartmaker.nl/> for
 	  information on the LART.
 
+config SA1100_NANOENGINE
+	bool "nanoEngine"
+	select CPU_FREQ_SA1110
+	select PCI
+	select PCI_NANOENGINE
+	help
+	  Say Y here if you are using the Bright Star Engineering nanoEngine.
+	  See <http://www.brightstareng.com/arm/nanoeng.htm> for information
+	  on the BSE nanoEngine.
+
 config SA1100_PLEB
 	bool "PLEB"
 	select CPU_FREQ_SA1100
diff --git a/arch/arm/mach-sa1100/Makefile b/arch/arm/mach-sa1100/Makefile
index 89349c1..e697691 100644
--- a/arch/arm/mach-sa1100/Makefile
+++ b/arch/arm/mach-sa1100/Makefile
@@ -37,6 +37,9 @@
 obj-$(CONFIG_SA1100_LART)		+= lart.o
 led-$(CONFIG_SA1100_LART)		+= leds-lart.o
 
+obj-$(CONFIG_SA1100_NANOENGINE)		+= nanoengine.o
+obj-$(CONFIG_PCI_NANOENGINE)		+= pci-nanoengine.o
+
 obj-$(CONFIG_SA1100_PLEB)		+= pleb.o
 
 obj-$(CONFIG_SA1100_SHANNON)		+= shannon.o
diff --git a/arch/arm/mach-sa1100/cpu-sa1100.c b/arch/arm/mach-sa1100/cpu-sa1100.c
index 96f7dc1..07d4e8b 100644
--- a/arch/arm/mach-sa1100/cpu-sa1100.c
+++ b/arch/arm/mach-sa1100/cpu-sa1100.c
@@ -94,48 +94,47 @@
 
 #include "generic.h"
 
-typedef struct {
+struct sa1100_dram_regs {
 	int speed;
 	u32 mdcnfg;
 	u32 mdcas0;
 	u32 mdcas1;
 	u32 mdcas2;
-} sa1100_dram_regs_t;
+};
 
 
 static struct cpufreq_driver sa1100_driver;
 
-static sa1100_dram_regs_t sa1100_dram_settings[] =
-{
-	/* speed,     mdcnfg,     mdcas0,     mdcas1,     mdcas2  clock frequency */
-	{  59000, 0x00dc88a3, 0xcccccccf, 0xfffffffc, 0xffffffff }, /*  59.0 MHz */
-	{  73700, 0x011490a3, 0xcccccccf, 0xfffffffc, 0xffffffff }, /*  73.7 MHz */
-	{  88500, 0x014e90a3, 0xcccccccf, 0xfffffffc, 0xffffffff }, /*  88.5 MHz */
-	{ 103200, 0x01889923, 0xcccccccf, 0xfffffffc, 0xffffffff }, /* 103.2 MHz */
-	{ 118000, 0x01c29923, 0x9999998f, 0xfffffff9, 0xffffffff }, /* 118.0 MHz */
-	{ 132700, 0x01fb2123, 0x9999998f, 0xfffffff9, 0xffffffff }, /* 132.7 MHz */
-	{ 147500, 0x02352123, 0x3333330f, 0xfffffff3, 0xffffffff }, /* 147.5 MHz */
-	{ 162200, 0x026b29a3, 0x38e38e1f, 0xfff8e38e, 0xffffffff }, /* 162.2 MHz */
-	{ 176900, 0x02a329a3, 0x71c71c1f, 0xfff1c71c, 0xffffffff }, /* 176.9 MHz */
-	{ 191700, 0x02dd31a3, 0xe38e383f, 0xffe38e38, 0xffffffff }, /* 191.7 MHz */
-	{ 206400, 0x03153223, 0xc71c703f, 0xffc71c71, 0xffffffff }, /* 206.4 MHz */
-	{ 221200, 0x034fba23, 0xc71c703f, 0xffc71c71, 0xffffffff }, /* 221.2 MHz */
-	{ 235900, 0x03853a23, 0xe1e1e07f, 0xe1e1e1e1, 0xffffffe1 }, /* 235.9 MHz */
-	{ 250700, 0x03bf3aa3, 0xc3c3c07f, 0xc3c3c3c3, 0xffffffc3 }, /* 250.7 MHz */
-	{ 265400, 0x03f7c2a3, 0xc3c3c07f, 0xc3c3c3c3, 0xffffffc3 }, /* 265.4 MHz */
-	{ 280200, 0x0431c2a3, 0x878780ff, 0x87878787, 0xffffff87 }, /* 280.2 MHz */
+static struct sa1100_dram_regs sa1100_dram_settings[] = {
+	/*speed,     mdcnfg,     mdcas0,     mdcas1,     mdcas2,   clock freq */
+	{ 59000, 0x00dc88a3, 0xcccccccf, 0xfffffffc, 0xffffffff},/*  59.0 MHz */
+	{ 73700, 0x011490a3, 0xcccccccf, 0xfffffffc, 0xffffffff},/*  73.7 MHz */
+	{ 88500, 0x014e90a3, 0xcccccccf, 0xfffffffc, 0xffffffff},/*  88.5 MHz */
+	{103200, 0x01889923, 0xcccccccf, 0xfffffffc, 0xffffffff},/* 103.2 MHz */
+	{118000, 0x01c29923, 0x9999998f, 0xfffffff9, 0xffffffff},/* 118.0 MHz */
+	{132700, 0x01fb2123, 0x9999998f, 0xfffffff9, 0xffffffff},/* 132.7 MHz */
+	{147500, 0x02352123, 0x3333330f, 0xfffffff3, 0xffffffff},/* 147.5 MHz */
+	{162200, 0x026b29a3, 0x38e38e1f, 0xfff8e38e, 0xffffffff},/* 162.2 MHz */
+	{176900, 0x02a329a3, 0x71c71c1f, 0xfff1c71c, 0xffffffff},/* 176.9 MHz */
+	{191700, 0x02dd31a3, 0xe38e383f, 0xffe38e38, 0xffffffff},/* 191.7 MHz */
+	{206400, 0x03153223, 0xc71c703f, 0xffc71c71, 0xffffffff},/* 206.4 MHz */
+	{221200, 0x034fba23, 0xc71c703f, 0xffc71c71, 0xffffffff},/* 221.2 MHz */
+	{235900, 0x03853a23, 0xe1e1e07f, 0xe1e1e1e1, 0xffffffe1},/* 235.9 MHz */
+	{250700, 0x03bf3aa3, 0xc3c3c07f, 0xc3c3c3c3, 0xffffffc3},/* 250.7 MHz */
+	{265400, 0x03f7c2a3, 0xc3c3c07f, 0xc3c3c3c3, 0xffffffc3},/* 265.4 MHz */
+	{280200, 0x0431c2a3, 0x878780ff, 0x87878787, 0xffffff87},/* 280.2 MHz */
 	{ 0, 0, 0, 0, 0 } /* last entry */
 };
 
 static void sa1100_update_dram_timings(int current_speed, int new_speed)
 {
-	sa1100_dram_regs_t *settings = sa1100_dram_settings;
+	struct sa1100_dram_regs *settings = sa1100_dram_settings;
 
 	/* find speed */
 	while (settings->speed != 0) {
-		if(new_speed == settings->speed)
+		if (new_speed == settings->speed)
 			break;
-		
+
 		settings++;
 	}
 
@@ -149,7 +148,7 @@
 		/* We're going FASTER, so first relax the memory
 		 * timings before changing the core frequency
 		 */
-		
+
 		/* Half the memory access clock */
 		MDCNFG |= MDCNFG_CDB2;
 
@@ -187,7 +186,7 @@
 	struct cpufreq_freqs freqs;
 
 	new_ppcr = sa11x0_freq_to_ppcr(target_freq);
-	switch(relation){
+	switch (relation) {
 	case CPUFREQ_RELATION_L:
 		if (sa11x0_ppcr_to_freq(new_ppcr) > policy->max)
 			new_ppcr--;
diff --git a/arch/arm/mach-sa1100/cpu-sa1110.c b/arch/arm/mach-sa1100/cpu-sa1110.c
index 7252874..675bf8e 100644
--- a/arch/arm/mach-sa1100/cpu-sa1110.c
+++ b/arch/arm/mach-sa1100/cpu-sa1110.c
@@ -16,28 +16,24 @@
  *
  * The SDRAM type can be passed on the command line as cpu_sa1110.sdram=type
  */
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/cpufreq.h>
 #include <linux/delay.h>
 #include <linux/init.h>
-#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
 
-#include <mach/hardware.h>
 #include <asm/cputype.h>
 #include <asm/mach-types.h>
-#include <asm/system.h>
+
+#include <mach/hardware.h>
 
 #include "generic.h"
 
 #undef DEBUG
 
-static struct cpufreq_driver sa1110_driver;
-
 struct sdram_params {
-	const char name[16];
+	const char name[20];
 	u_char  rows;		/* bits				 */
 	u_char  cas_latency;	/* cycles			 */
 	u_char  tck;		/* clock cycle time (ns)	 */
@@ -107,6 +103,15 @@
 		.twr		= 8,
 		.refresh	= 64000,
 		.cas_latency	= 3,
+	}, {	/* Micron MT48LC8M16A2TG-75 */
+		.name		= "MT48LC8M16A2TG-75",
+		.rows		= 12,
+		.tck		= 8,
+		.trcd		= 20,
+		.trp		= 20,
+		.twr		= 8,
+		.refresh	= 64000,
+		.cas_latency	= 3,
 	},
 };
 
@@ -180,11 +185,13 @@
 		sd->mdrefr |= MDREFR_K1DB2;
 
 	/* initial number of '1's in MDCAS + 1 */
-	set_mdcas(sd->mdcas, sd_khz >= 62000, ns_to_cycles(sdram->trcd, mem_khz));
+	set_mdcas(sd->mdcas, sd_khz >= 62000,
+		ns_to_cycles(sdram->trcd, mem_khz));
 
 #ifdef DEBUG
-	printk("MDCNFG: %08x MDREFR: %08x MDCAS0: %08x MDCAS1: %08x MDCAS2: %08x\n",
-		sd->mdcnfg, sd->mdrefr, sd->mdcas[0], sd->mdcas[1], sd->mdcas[2]);
+	printk(KERN_DEBUG "MDCNFG: %08x MDREFR: %08x MDCAS0: %08x MDCAS1: %08x MDCAS2: %08x\n",
+		sd->mdcnfg, sd->mdrefr, sd->mdcas[0], sd->mdcas[1],
+		sd->mdcas[2]);
 #endif
 }
 
@@ -213,7 +220,7 @@
 
 #ifdef DEBUG
 	mdelay(250);
-	printk("new dri value = %d\n", dri);
+	printk(KERN_DEBUG "new dri value = %d\n", dri);
 #endif
 
 	sdram_set_refresh(dri);
@@ -232,7 +239,7 @@
 	unsigned long flags;
 	unsigned int ppcr, unused;
 
-	switch(relation){
+	switch (relation) {
 	case CPUFREQ_RELATION_L:
 		ppcr = sa11x0_freq_to_ppcr(target_freq);
 		if (sa11x0_ppcr_to_freq(ppcr) > policy->max)
@@ -280,11 +287,10 @@
 	 * We wait 20ms to be safe.
 	 */
 	sdram_set_refresh(2);
-	if (!irqs_disabled()) {
+	if (!irqs_disabled())
 		msleep(20);
-	} else {
+	else
 		mdelay(20);
-	}
 
 	/*
 	 * Reprogram the DRAM timings with interrupts disabled, and
@@ -295,7 +301,7 @@
 	local_irq_save(flags);
 	asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (0));
 	udelay(10);
-	__asm__ __volatile__("					\n\
+	__asm__ __volatile__("\n\
 		b	2f					\n\
 		.align	5					\n\
 1:		str	%3, [%1, #0]		@ MDCNFG	\n\
@@ -336,7 +342,9 @@
 	return 0;
 }
 
-static struct cpufreq_driver sa1110_driver = {
+/* sa1110_driver needs __refdata because it must remain after init registers
+ * it with cpufreq_register_driver() */
+static struct cpufreq_driver sa1110_driver __refdata = {
 	.flags		= CPUFREQ_STICKY,
 	.verify		= sa11x0_verify_speed,
 	.target		= sa1110_target,
@@ -349,7 +357,8 @@
 {
 	struct sdram_params *sdram;
 
-	for (sdram = sdram_tbl; sdram < sdram_tbl + ARRAY_SIZE(sdram_tbl); sdram++)
+	for (sdram = sdram_tbl; sdram < sdram_tbl + ARRAY_SIZE(sdram_tbl);
+	     sdram++)
 		if (strcmp(name, sdram->name) == 0)
 			return sdram;
 
@@ -369,14 +378,14 @@
 	if (!name[0]) {
 		if (machine_is_assabet())
 			name = "TC59SM716-CL3";
-
 		if (machine_is_pt_system3())
 			name = "K4S641632D";
-
 		if (machine_is_h3100())
 			name = "KM416S4030CT";
 		if (machine_is_jornada720())
-		        name = "K4S281632B-1H";
+			name = "K4S281632B-1H";
+		if (machine_is_nanoengine())
+			name = "MT48LC8M16A2TG-75";
 	}
 
 	sdram = sa1110_find_sdram(name);
diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c
index 3c1fcd6..3555d61 100644
--- a/arch/arm/mach-sa1100/generic.c
+++ b/arch/arm/mach-sa1100/generic.c
@@ -163,10 +163,15 @@
 
 static struct resource sa11x0udc_resources[] = {
 	[0] = {
-		.start	= 0x80000000,
-		.end	= 0x8000ffff,
+		.start	= __PREG(Ser0UDCCR),
+		.end	= __PREG(Ser0UDCCR) + 0xffff,
 		.flags	= IORESOURCE_MEM,
 	},
+	[1] = {
+		.start	= IRQ_Ser0UDC,
+		.end	= IRQ_Ser0UDC,
+		.flags	= IORESOURCE_IRQ,
+	},
 };
 
 static u64 sa11x0udc_dma_mask = 0xffffffffUL;
@@ -184,10 +189,15 @@
 
 static struct resource sa11x0uart1_resources[] = {
 	[0] = {
-		.start	= 0x80010000,
-		.end	= 0x8001ffff,
+		.start	= __PREG(Ser1UTCR0),
+		.end	= __PREG(Ser1UTCR0) + 0xffff,
 		.flags	= IORESOURCE_MEM,
 	},
+	[1] = {
+		.start	= IRQ_Ser1UART,
+		.end	= IRQ_Ser1UART,
+		.flags	= IORESOURCE_IRQ,
+	},
 };
 
 static struct platform_device sa11x0uart1_device = {
@@ -199,10 +209,15 @@
 
 static struct resource sa11x0uart3_resources[] = {
 	[0] = {
-		.start	= 0x80050000,
-		.end	= 0x8005ffff,
+		.start	= __PREG(Ser3UTCR0),
+		.end	= __PREG(Ser3UTCR0) + 0xffff,
 		.flags	= IORESOURCE_MEM,
 	},
+	[1] = {
+		.start	= IRQ_Ser3UART,
+		.end	= IRQ_Ser3UART,
+		.flags	= IORESOURCE_IRQ,
+	},
 };
 
 static struct platform_device sa11x0uart3_device = {
@@ -214,10 +229,15 @@
 
 static struct resource sa11x0mcp_resources[] = {
 	[0] = {
-		.start	= 0x80060000,
-		.end	= 0x8006ffff,
+		.start	= __PREG(Ser4MCCR0),
+		.end	= __PREG(Ser4MCCR0) + 0xffff,
 		.flags	= IORESOURCE_MEM,
 	},
+	[1] = {
+		.start	= IRQ_Ser4MCP,
+		.end	= IRQ_Ser4MCP,
+		.flags	= IORESOURCE_IRQ,
+	},
 };
 
 static u64 sa11x0mcp_dma_mask = 0xffffffffUL;
@@ -244,6 +264,11 @@
 		.end	= 0x8007ffff,
 		.flags	= IORESOURCE_MEM,
 	},
+	[1] = {
+		.start	= IRQ_Ser4SSP,
+		.end	= IRQ_Ser4SSP,
+		.flags	= IORESOURCE_IRQ,
+	},
 };
 
 static u64 sa11x0ssp_dma_mask = 0xffffffffUL;
diff --git a/arch/arm/mach-sa1100/include/mach/hardware.h b/arch/arm/mach-sa1100/include/mach/hardware.h
index 99f5856..967ae76 100644
--- a/arch/arm/mach-sa1100/include/mach/hardware.h
+++ b/arch/arm/mach-sa1100/include/mach/hardware.h
@@ -76,4 +76,12 @@
 #include "SA-1101.h"
 #endif
 
+#if defined(CONFIG_ARCH_SA1100) && defined(CONFIG_PCI)
+#define PCIBIOS_MIN_IO		0
+#define PCIBIOS_MIN_MEM		0
+#define pcibios_assign_all_busses()	1
+#define HAVE_ARCH_PCI_SET_DMA_MASK	1
+#endif
+
+
 #endif  /* _ASM_ARCH_HARDWARE_H */
diff --git a/arch/arm/mach-sa1100/include/mach/nanoengine.h b/arch/arm/mach-sa1100/include/mach/nanoengine.h
new file mode 100644
index 0000000..14f8382
--- /dev/null
+++ b/arch/arm/mach-sa1100/include/mach/nanoengine.h
@@ -0,0 +1,52 @@
+/*
+ * arch/arm/mach-sa1100/include/mach/nanoengine.h
+ *
+ * This file contains the hardware specific definitions for nanoEngine.
+ * Only include this file from SA1100-specific files.
+ *
+ * Copyright (C) 2010 Marcelo Roberto Jimenez <mroberto@cpti.cetuc.puc-rio.br>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#ifndef __ASM_ARCH_NANOENGINE_H
+#define __ASM_ARCH_NANOENGINE_H
+
+#include <mach/irqs.h>
+
+#define GPIO_PC_READY0	GPIO_GPIO(11) /* ready for socket 0 (active high)*/
+#define GPIO_PC_READY1	GPIO_GPIO(12) /* ready for socket 1 (active high) */
+#define GPIO_PC_CD0	GPIO_GPIO(13) /* detect for socket 0 (active low) */
+#define GPIO_PC_CD1	GPIO_GPIO(14) /* detect for socket 1 (active low) */
+#define GPIO_PC_RESET0	GPIO_GPIO(15) /* reset socket 0 */
+#define GPIO_PC_RESET1	GPIO_GPIO(16) /* reset socket 1 */
+
+#define NANOENGINE_IRQ_GPIO_PCI		IRQ_GPIO0
+#define NANOENGINE_IRQ_GPIO_PC_READY0	IRQ_GPIO11
+#define NANOENGINE_IRQ_GPIO_PC_READY1	IRQ_GPIO12
+#define NANOENGINE_IRQ_GPIO_PC_CD0	IRQ_GPIO13
+#define NANOENGINE_IRQ_GPIO_PC_CD1	IRQ_GPIO14
+
+/*
+ * nanoEngine Memory Map:
+ *
+ * 0000.0000 - 003F.0000 -   4 MB Flash
+ * C000.0000 - C1FF.FFFF -  32 MB SDRAM
+ * 1860.0000 - 186F.FFFF -   1 MB Internal PCI Memory Read/Write
+ * 18A1.0000 - 18A1.FFFF -  64 KB Internal PCI Config Space
+ * 4000.0000 - 47FF.FFFF - 128 MB External Bus I/O - Multiplexed Mode
+ * 4800.0000 - 4FFF.FFFF - 128 MB External Bus I/O - Non-Multiplexed Mode
+ *
+ */
+
+#define NANO_PCI_MEM_RW_PHYS		0x18600000
+#define NANO_PCI_MEM_RW_VIRT		0xf1000000
+#define NANO_PCI_MEM_RW_SIZE		SZ_1M
+#define NANO_PCI_CONFIG_SPACE_PHYS	0x18A10000
+#define NANO_PCI_CONFIG_SPACE_VIRT	0xf2000000
+#define NANO_PCI_CONFIG_SPACE_SIZE	SZ_64K
+
+#endif
+
diff --git a/arch/arm/mach-sa1100/nanoengine.c b/arch/arm/mach-sa1100/nanoengine.c
new file mode 100644
index 0000000..72087f0
--- /dev/null
+++ b/arch/arm/mach-sa1100/nanoengine.c
@@ -0,0 +1,119 @@
+/*
+ * linux/arch/arm/mach-sa1100/nanoengine.c
+ *
+ * Bright Star Engineering's nanoEngine board init code.
+ *
+ * Copyright (C) 2010 Marcelo Roberto Jimenez <mroberto@cpti.cetuc.puc-rio.br>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/root_dev.h>
+
+#include <asm/mach-types.h>
+#include <asm/setup.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+#include <asm/mach/map.h>
+#include <asm/mach/serial_sa1100.h>
+
+#include <mach/hardware.h>
+#include <mach/nanoengine.h>
+
+#include "generic.h"
+
+/* Flash bank 0 */
+static struct mtd_partition nanoengine_partitions[] = {
+	{
+		.name	= "nanoEngine boot firmware and parameter table",
+		.size		= 0x00010000,  /* 32K */
+		.offset		= 0,
+		.mask_flags	= MTD_WRITEABLE,
+	}, {
+		.name		= "kernel/initrd reserved",
+		.size		= 0x002f0000,
+		.offset		= 0x00010000,
+		.mask_flags	= MTD_WRITEABLE,
+	}, {
+		.name		= "experimental filesystem allocation",
+		.size		= 0x00100000,
+		.offset		= 0x00300000,
+		.mask_flags	= MTD_WRITEABLE,
+	}
+};
+
+static struct flash_platform_data nanoengine_flash_data = {
+	.map_name	= "jedec_probe",
+	.parts		= nanoengine_partitions,
+	.nr_parts	= ARRAY_SIZE(nanoengine_partitions),
+};
+
+static struct resource nanoengine_flash_resources[] = {
+	{
+		.start	= SA1100_CS0_PHYS,
+		.end	= SA1100_CS0_PHYS + SZ_32M - 1,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= SA1100_CS1_PHYS,
+		.end	= SA1100_CS1_PHYS + SZ_32M - 1,
+		.flags	= IORESOURCE_MEM,
+	}
+};
+
+static struct map_desc nanoengine_io_desc[] __initdata = {
+	{
+		/* System Registers */
+		.virtual	= 0xf0000000,
+		.pfn		= __phys_to_pfn(0x10000000),
+		.length		= 0x00100000,
+		.type		= MT_DEVICE
+	}, {
+		/* Internal PCI Memory Read/Write */
+		.virtual	= NANO_PCI_MEM_RW_VIRT,
+		.pfn		= __phys_to_pfn(NANO_PCI_MEM_RW_PHYS),
+		.length		= NANO_PCI_MEM_RW_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		/* Internal PCI Config Space */
+		.virtual	= NANO_PCI_CONFIG_SPACE_VIRT,
+		.pfn		= __phys_to_pfn(NANO_PCI_CONFIG_SPACE_PHYS),
+		.length		= NANO_PCI_CONFIG_SPACE_SIZE,
+		.type		= MT_DEVICE
+	}
+};
+
+static void __init nanoengine_map_io(void)
+{
+	sa1100_map_io();
+	iotable_init(nanoengine_io_desc, ARRAY_SIZE(nanoengine_io_desc));
+
+	sa1100_register_uart(0, 1);
+	sa1100_register_uart(1, 2);
+	sa1100_register_uart(2, 3);
+	Ser1SDCR0 |= SDCR0_UART;
+	/* disable IRDA -- UART2 is used as a normal serial port */
+	Ser2UTCR4 = 0;
+	Ser2HSCR0 = 0;
+}
+
+static void __init nanoengine_init(void)
+{
+	sa11x0_register_mtd(&nanoengine_flash_data, nanoengine_flash_resources,
+		ARRAY_SIZE(nanoengine_flash_resources));
+}
+
+MACHINE_START(NANOENGINE, "BSE nanoEngine")
+	.boot_params	= 0xc0000000,
+	.map_io		= nanoengine_map_io,
+	.init_irq	= sa1100_init_irq,
+	.timer		= &sa1100_timer,
+	.init_machine	= nanoengine_init,
+MACHINE_END
diff --git a/arch/arm/mach-sa1100/pci-nanoengine.c b/arch/arm/mach-sa1100/pci-nanoengine.c
new file mode 100644
index 0000000..fba7a91
--- /dev/null
+++ b/arch/arm/mach-sa1100/pci-nanoengine.c
@@ -0,0 +1,284 @@
+/*
+ * linux/arch/arm/mach-sa1100/pci-nanoengine.c
+ *
+ * PCI functions for BSE nanoEngine PCI
+ *
+ * Copyright (C) 2010 Marcelo Roberto Jimenez <mroberto@cpti.cetuc.puc-rio.br>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/kernel.h>
+#include <linux/irq.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+
+#include <asm/mach/pci.h>
+#include <asm/mach-types.h>
+
+#include <mach/nanoengine.h>
+
+static DEFINE_SPINLOCK(nano_lock);
+
+static int nanoengine_get_pci_address(struct pci_bus *bus,
+	unsigned int devfn, int where, unsigned long *address)
+{
+	int ret = PCIBIOS_DEVICE_NOT_FOUND;
+	unsigned int busnr = bus->number;
+
+	*address = NANO_PCI_CONFIG_SPACE_VIRT +
+		((bus->number << 16) | (devfn << 8) | (where & ~3));
+
+	ret = (busnr > 255 || devfn > 255 || where > 255) ?
+		PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
+
+	return ret;
+}
+
+static int nanoengine_read_config(struct pci_bus *bus, unsigned int devfn, int where,
+	int size, u32 *val)
+{
+	int ret;
+	unsigned long address;
+	unsigned long flags;
+	u32 v;
+
+	/* nanoEngine PCI bridge does not return -1 for a non-existing
+	 * device. We must fake the answer. We know that the only valid
+	 * device is device zero at bus 0, which is the network chip. */
+	if (bus->number != 0 || (devfn >> 3) != 0) {
+		v = -1;
+		nanoengine_get_pci_address(bus, devfn, where, &address);
+		goto exit_function;
+	}
+
+	spin_lock_irqsave(&nano_lock, flags);
+
+	ret = nanoengine_get_pci_address(bus, devfn, where, &address);
+	if (ret != PCIBIOS_SUCCESSFUL)
+		return ret;
+	v = __raw_readl(address);
+
+	spin_unlock_irqrestore(&nano_lock, flags);
+
+	v >>= ((where & 3) * 8);
+	v &= (unsigned long)(-1) >> ((4 - size) * 8);
+
+exit_function:
+	*val = v;
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int nanoengine_write_config(struct pci_bus *bus, unsigned int devfn, int where,
+	int size, u32 val)
+{
+	int ret;
+	unsigned long address;
+	unsigned long flags;
+	unsigned shift;
+	u32 v;
+
+	shift = (where & 3) * 8;
+
+	spin_lock_irqsave(&nano_lock, flags);
+
+	ret = nanoengine_get_pci_address(bus, devfn, where, &address);
+	if (ret != PCIBIOS_SUCCESSFUL)
+		return ret;
+	v = __raw_readl(address);
+	switch (size) {
+	case 1:
+		v &= ~(0xFF << shift);
+		v |= val << shift;
+		break;
+	case 2:
+		v &= ~(0xFFFF << shift);
+		v |= val << shift;
+		break;
+	case 4:
+		v = val;
+		break;
+	}
+	__raw_writel(v, address);
+
+	spin_unlock_irqrestore(&nano_lock, flags);
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops pci_nano_ops = {
+	.read	= nanoengine_read_config,
+	.write	= nanoengine_write_config,
+};
+
+static int __init pci_nanoengine_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	return NANOENGINE_IRQ_GPIO_PCI;
+}
+
+struct pci_bus * __init pci_nanoengine_scan_bus(int nr, struct pci_sys_data *sys)
+{
+	return pci_scan_bus(sys->busnr, &pci_nano_ops, sys);
+}
+
+static struct resource pci_io_ports = {
+	.name	= "PCI IO",
+	.start	= 0x400,
+	.end	= 0x7FF,
+	.flags	= IORESOURCE_IO,
+};
+
+static struct resource pci_non_prefetchable_memory = {
+	.name	= "PCI non-prefetchable",
+	.start	= NANO_PCI_MEM_RW_PHYS,
+	/* nanoEngine documentation says there is a 1 Megabyte window here,
+	 * but PCI reports just 128 + 8 kbytes. */
+	.end	= NANO_PCI_MEM_RW_PHYS + NANO_PCI_MEM_RW_SIZE - 1,
+/*	.end	= NANO_PCI_MEM_RW_PHYS + SZ_128K + SZ_8K - 1,*/
+	.flags	= IORESOURCE_MEM,
+};
+
+/*
+ * nanoEngine PCI reports 1 Megabyte of prefetchable memory, but it
+ * overlaps with previously defined memory.
+ *
+ * Here is what happens:
+ *
+# dmesg
+...
+pci 0000:00:00.0: [8086:1209] type 0 class 0x000200
+pci 0000:00:00.0: reg 10: [mem 0x00021000-0x00021fff]
+pci 0000:00:00.0: reg 14: [io  0x0000-0x003f]
+pci 0000:00:00.0: reg 18: [mem 0x00000000-0x0001ffff]
+pci 0000:00:00.0: reg 30: [mem 0x00000000-0x000fffff pref]
+pci 0000:00:00.0: supports D1 D2
+pci 0000:00:00.0: PME# supported from D0 D1 D2 D3hot
+pci 0000:00:00.0: PME# disabled
+PCI: bus0: Fast back to back transfers enabled
+pci 0000:00:00.0: BAR 6: can't assign mem pref (size 0x100000)
+pci 0000:00:00.0: BAR 2: assigned [mem 0x18600000-0x1861ffff]
+pci 0000:00:00.0: BAR 2: set to [mem 0x18600000-0x1861ffff] (PCI address [0x0-0x1ffff])
+pci 0000:00:00.0: BAR 0: assigned [mem 0x18620000-0x18620fff]
+pci 0000:00:00.0: BAR 0: set to [mem 0x18620000-0x18620fff] (PCI address [0x20000-0x20fff])
+pci 0000:00:00.0: BAR 1: assigned [io  0x0400-0x043f]
+pci 0000:00:00.0: BAR 1: set to [io  0x0400-0x043f] (PCI address [0x0-0x3f])
+ *
+ * On the other hand, if we do not request the prefetchable memory resource,
+ * linux will alloc it first and the two non-prefetchable memory areas that
+ * are our real interest will not be mapped. So we choose to map it to an
+ * unused area. It gets recognized as expansion ROM, but becomes disabled.
+ *
+ * Here is what happens then:
+ *
+# dmesg
+...
+pci 0000:00:00.0: [8086:1209] type 0 class 0x000200
+pci 0000:00:00.0: reg 10: [mem 0x00021000-0x00021fff]
+pci 0000:00:00.0: reg 14: [io  0x0000-0x003f]
+pci 0000:00:00.0: reg 18: [mem 0x00000000-0x0001ffff]
+pci 0000:00:00.0: reg 30: [mem 0x00000000-0x000fffff pref]
+pci 0000:00:00.0: supports D1 D2
+pci 0000:00:00.0: PME# supported from D0 D1 D2 D3hot
+pci 0000:00:00.0: PME# disabled
+PCI: bus0: Fast back to back transfers enabled
+pci 0000:00:00.0: BAR 6: assigned [mem 0x78000000-0x780fffff pref]
+pci 0000:00:00.0: BAR 2: assigned [mem 0x18600000-0x1861ffff]
+pci 0000:00:00.0: BAR 2: set to [mem 0x18600000-0x1861ffff] (PCI address [0x0-0x1ffff])
+pci 0000:00:00.0: BAR 0: assigned [mem 0x18620000-0x18620fff]
+pci 0000:00:00.0: BAR 0: set to [mem 0x18620000-0x18620fff] (PCI address [0x20000-0x20fff])
+pci 0000:00:00.0: BAR 1: assigned [io  0x0400-0x043f]
+pci 0000:00:00.0: BAR 1: set to [io  0x0400-0x043f] (PCI address [0x0-0x3f])
+
+# lspci -vv -s 0000:00:00.0
+00:00.0 Class 0200: Device 8086:1209 (rev 09)
+        Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr+ Stepping- SERR+ FastB2B- DisINTx-
+        Status: Cap+ 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR+ <PERR+ INTx-
+        Latency: 0 (2000ns min, 14000ns max), Cache Line Size: 32 bytes
+        Interrupt: pin A routed to IRQ 0
+        Region 0: Memory at 18620000 (32-bit, non-prefetchable) [size=4K]
+        Region 1: I/O ports at 0400 [size=64]
+        Region 2: [virtual] Memory at 18600000 (32-bit, non-prefetchable) [size=128K]
+        [virtual] Expansion ROM at 78000000 [disabled] [size=1M]
+        Capabilities: [dc] Power Management version 2
+                Flags: PMEClk- DSI+ D1+ D2+ AuxCurrent=0mA PME(D0+,D1+,D2+,D3hot+,D3cold-)
+                Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=2 PME-
+        Kernel driver in use: e100
+        Kernel modules: e100
+ *
+ */
+static struct resource pci_prefetchable_memory = {
+	.name	= "PCI prefetchable",
+	.start	= 0x78000000,
+	.end	= 0x78000000 + NANO_PCI_MEM_RW_SIZE - 1,
+	.flags	= IORESOURCE_MEM  | IORESOURCE_PREFETCH,
+};
+
+static int __init pci_nanoengine_setup_resources(struct resource **resource)
+{
+	if (request_resource(&ioport_resource, &pci_io_ports)) {
+		printk(KERN_ERR "PCI: unable to allocate io port region\n");
+		return -EBUSY;
+	}
+	if (request_resource(&iomem_resource, &pci_non_prefetchable_memory)) {
+		release_resource(&pci_io_ports);
+		printk(KERN_ERR "PCI: unable to allocate non prefetchable\n");
+		return -EBUSY;
+	}
+	if (request_resource(&iomem_resource, &pci_prefetchable_memory)) {
+		release_resource(&pci_io_ports);
+		release_resource(&pci_non_prefetchable_memory);
+		printk(KERN_ERR "PCI: unable to allocate prefetchable\n");
+		return -EBUSY;
+	}
+	resource[0] = &pci_io_ports;
+	resource[1] = &pci_non_prefetchable_memory;
+	resource[2] = &pci_prefetchable_memory;
+
+	return 1;
+}
+
+int __init pci_nanoengine_setup(int nr, struct pci_sys_data *sys)
+{
+	int ret = 0;
+
+	if (nr == 0) {
+		sys->mem_offset = NANO_PCI_MEM_RW_PHYS;
+		sys->io_offset = 0x400;
+		ret = pci_nanoengine_setup_resources(sys->resource);
+		/* Enable alternate memory bus master mode, see
+		 * "Intel StrongARM SA1110 Developer's Manual",
+		 * section 10.8, "Alternate Memory Bus Master Mode". */
+		GPDR = (GPDR & ~GPIO_MBREQ) | GPIO_MBGNT;
+		GAFR |= GPIO_MBGNT | GPIO_MBREQ;
+		TUCR |= TUCR_MBGPIO;
+	}
+
+	return ret;
+}
+
+static struct hw_pci nanoengine_pci __initdata = {
+	.map_irq		= pci_nanoengine_map_irq,
+	.nr_controllers		= 1,
+	.scan			= pci_nanoengine_scan_bus,
+	.setup			= pci_nanoengine_setup,
+};
+
+static int __init nanoengine_pci_init(void)
+{
+	if (machine_is_nanoengine())
+		pci_common_init(&nanoengine_pci);
+	return 0;
+}
+
+subsys_initcall(nanoengine_pci_init);
diff --git a/arch/arm/mach-sa1100/simpad.c b/arch/arm/mach-sa1100/simpad.c
index 27692d0..cfb7607 100644
--- a/arch/arm/mach-sa1100/simpad.c
+++ b/arch/arm/mach-sa1100/simpad.c
@@ -166,9 +166,6 @@
 	PCFR = 0;
 	PSDR = 0;
 
-	sa11x0_register_mtd(&simpad_flash_data, simpad_flash_resources,
-			      ARRAY_SIZE(simpad_flash_resources));
-	sa11x0_register_mcp(&simpad_mcp_data);
 }
 
 static void simpad_power_off(void)
@@ -216,6 +213,10 @@
 
 	pm_power_off = simpad_power_off;
 
+	sa11x0_register_mtd(&simpad_flash_data, simpad_flash_resources,
+			      ARRAY_SIZE(simpad_flash_resources));
+	sa11x0_register_mcp(&simpad_mcp_data);
+
 	ret = platform_add_devices(devices, ARRAY_SIZE(devices));
 	if(ret)
 		printk(KERN_WARNING "simpad: Unable to register mq200 framebuffer device");
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c
index d440e5f..ac429ff 100644
--- a/arch/arm/mach-shmobile/board-ap4evb.c
+++ b/arch/arm/mach-shmobile/board-ap4evb.c
@@ -61,6 +61,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
+#include <asm/setup.h>
 
 /*
  * Address	Interface		BusWidth	note
diff --git a/arch/arm/mach-shmobile/include/mach/head-ap4evb.txt b/arch/arm/mach-shmobile/include/mach/head-ap4evb.txt
new file mode 100644
index 0000000..e3ebfa7
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/head-ap4evb.txt
@@ -0,0 +1,87 @@
+LIST "partner-jet-setup.txt"
+LIST "(C) Copyright 2010 Renesas Solutions Corp"
+LIST "Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>"
+
+LIST "RWT Setting"
+EW 0xE6020004, 0xA500
+EW 0xE6030004, 0xA500
+
+DD 0x01001000, 0x01001000
+
+LIST "GPIO Setting"
+EB 0xE6051013, 0xA2
+
+LIST "CPG"
+ED 0xE6150080, 0x00000180
+ED 0xE61500C0, 0x00000002
+
+WAIT 1, 0xFE40009C
+
+LIST "FRQCR"
+ED 0xE6150000, 0x2D1305C3
+ED 0xE61500E0, 0x9E40358E
+ED 0xE6150004, 0x80331050
+
+WAIT 1, 0xFE40009C
+
+ED 0xE61500E4, 0x00002000
+
+WAIT 1, 0xFE40009C
+
+LIST "PLL"
+ED 0xE6150028, 0x00004000
+
+WAIT 1, 0xFE40009C
+
+ED 0xE615002C, 0x93000040
+
+WAIT 1, 0xFE40009C
+
+LIST "BSC"
+ED 0xFEC10000, 0x00E0001B
+
+LIST "SBSC1"
+ED 0xFE400354, 0x01AD8000
+ED 0xFE400354, 0x01AD8001
+
+WAIT 5, 0xFE40009C
+
+ED 0xFE400008, 0xBCC90151
+ED 0xFE400040, 0x41774113
+ED 0xFE400044, 0x2712E229
+ED 0xFE400048, 0x20C18505
+ED 0xFE40004C, 0x00110209
+ED 0xFE400010, 0x00000087
+
+WAIT 10, 0xFE40009C
+
+ED 0xFE400084, 0x0000003F
+EB 0xFE500000, 0x00
+
+WAIT 5, 0xFE40009C
+
+ED 0xFE400084, 0x0000FF0A
+EB 0xFE500000, 0x00
+
+WAIT 1, 0xFE40009C
+
+ED 0xFE400084, 0x00002201
+EB 0xFE500000, 0x00
+ED 0xFE400084, 0x00000302
+EB 0xFE500000, 0x00
+EB 0xFE5C0000, 0x00
+ED 0xFE400008, 0xBCC90159
+ED 0xFE40008C, 0x88800004
+ED 0xFE400094, 0x00000004
+ED 0xFE400028, 0xA55A0032
+ED 0xFE40002C, 0xA55A000C
+ED 0xFE400020, 0xA55A2048
+ED 0xFE400008, 0xBCC90959
+
+LIST "Change CPGA setting"
+ED 0xE61500E0, 0x9E40352E
+ED 0xE6150004, 0x80331050
+
+WAIT 1, 0xFE40009C
+
+ED 0xE6150354, 0x00000002
diff --git a/arch/arm/mach-shmobile/include/mach/zboot.h b/arch/arm/mach-shmobile/include/mach/zboot.h
new file mode 100644
index 0000000..3ad86b7
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/zboot.h
@@ -0,0 +1,20 @@
+#ifndef ZBOOT_H
+#define ZBOOT_H
+
+#include <asm/mach-types.h>
+#include <mach/zboot_macros.h>
+
+/**************************************************
+ *
+ *		board specific settings
+ *
+ **************************************************/
+
+#ifdef CONFIG_MACH_AP4EVB
+#define MACH_TYPE	MACH_TYPE_AP4EVB
+#include "mach/head-ap4evb.txt"
+#else
+#error "unsupported board."
+#endif
+
+#endif /* ZBOOT_H */
diff --git a/arch/arm/mach-shmobile/include/mach/zboot_macros.h b/arch/arm/mach-shmobile/include/mach/zboot_macros.h
new file mode 100644
index 0000000..aa6111f
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/zboot_macros.h
@@ -0,0 +1,65 @@
+#ifndef __ZBOOT_MACRO_H
+#define __ZBOOT_MACRO_H
+
+/* The LIST command is used to include comments in the script */
+.macro	LIST comment
+.endm
+
+/* The ED command is used to write a 32-bit word */
+.macro ED, addr, data
+	LDR	r0, 1f
+	LDR	r1, 2f
+	STR	r1, [r0]
+	B	3f
+1 :	.long	\addr
+2 :	.long	\data
+3 :
+.endm
+
+/* The EW command is used to write a 16-bit word */
+.macro EW, addr, data
+	LDR	r0, 1f
+	LDR	r1, 2f
+	STRH	r1, [r0]
+	B	3f
+1 :	.long	\addr
+2 :	.long	\data
+3 :
+.endm
+
+/* The EB command is used to write an 8-bit word */
+.macro EB, addr, data
+	LDR	r0, 1f
+	LDR	r1, 2f
+	STRB	r1, [r0]
+	B	3f
+1 :	.long	\addr
+2 :	.long	\data
+3 :
+.endm
+
+/* The WAIT command is used to delay the execution */
+.macro  WAIT, time, reg
+	LDR	r1, 1f
+	LDR	r0, 2f
+	STR	r0, [r1]
+10 :
+	LDR	r0, [r1]
+	CMP	r0, #0x00000000
+	BNE	10b
+	NOP
+	B	3f
+1 :	.long	\reg
+2 :	.long	\time * 100
+3 :
+.endm
+
+/* The DD command is used to read a 32-bit word */
+.macro  DD, start, end
+	LDR	r1, 1f
+	B	2f
+1 :	.long	\start
+2 :
+.endm
+
+#endif /* __ZBOOT_MACRO_H */
diff --git a/arch/arm/mach-tegra/include/mach/entry-macro.S b/arch/arm/mach-tegra/include/mach/entry-macro.S
index 2ba9e5c..dd165c5 100644
--- a/arch/arm/mach-tegra/include/mach/entry-macro.S
+++ b/arch/arm/mach-tegra/include/mach/entry-macro.S
@@ -16,8 +16,8 @@
 #include <mach/io.h>
 
 #if defined(CONFIG_ARM_GIC)
-
-#include <asm/hardware/gic.h>
+#define HAVE_GET_IRQNR_PREAMBLE
+#include <asm/hardware/entry-macro-gic.S>
 
 	/* Uses the GIC interrupt controller built into the cpu */
 #define ICTRL_BASE (IO_CPU_VIRT + 0x100)
@@ -32,68 +32,6 @@
 
 	.macro  arch_ret_to_user, tmp1, tmp2
 	.endm
-
-	/*
-	 * The interrupt numbering scheme is defined in the
-	 * interrupt controller spec.  To wit:
-	 *
-	 * Interrupts 0-15 are IPI
-	 * 16-28 are reserved
-	 * 29-31 are local.  We allow 30 to be used for the watchdog.
-	 * 32-1020 are global
-	 * 1021-1022 are reserved
-	 * 1023 is "spurious" (no interrupt)
-	 *
-	 * For now, we ignore all local interrupts so only return an interrupt
-	 * if it's between 30 and 1020.  The test_for_ipi routine below will
-	 * pick up on IPIs.
-	 *
-	 * A simple read from the controller will tell us the number of the
-	 * highest priority enabled interrupt.  We then just need to check
-	 * whether it is in the valid range for an IRQ (30-1020 inclusive).
-	 */
-
-	.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-
-	/* bits 12-10 = src CPU, 9-0 = int # */
-	ldr     \irqstat, [\base, #GIC_CPU_INTACK]
-
-	ldr		\tmp, =1021
-
-	bic     \irqnr, \irqstat, #0x1c00
-
-	cmp     \irqnr, #29
-	cmpcc	\irqnr, \irqnr
-	cmpne	\irqnr, \tmp
-	cmpcs	\irqnr, \irqnr
-
-	.endm
-
-	/* We assume that irqstat (the raw value of the IRQ acknowledge
-	 * register) is preserved from the macro above.
-	 * If there is an IPI, we immediately signal end of interrupt on the
-	 * controller, since this requires the original irqstat value which
-	 * we won't easily be able to recreate later.
-	 */
-
-	.macro test_for_ipi, irqnr, irqstat, base, tmp
-	bic	\irqnr, \irqstat, #0x1c00
-	cmp	\irqnr, #16
-	strcc	\irqstat, [\base, #GIC_CPU_EOI]
-	cmpcs	\irqnr, \irqnr
-	.endm
-
-	/* As above, this assumes that irqstat and base are preserved.. */
-
-	.macro test_for_ltirq, irqnr, irqstat, base, tmp
-	bic	\irqnr, \irqstat, #0x1c00
-	mov 	\tmp, #0
-	cmp	\irqnr, #29
-	moveq	\tmp, #1
-	streq	\irqstat, [\base, #GIC_CPU_EOI]
-	cmp	\tmp, #0
-	.endm
-
 #else
 	/* legacy interrupt controller for AP16 */
 	.macro	disable_fiq
diff --git a/arch/arm/mach-tegra/include/mach/io.h b/arch/arm/mach-tegra/include/mach/io.h
index f0981b1..4cea223 100644
--- a/arch/arm/mach-tegra/include/mach/io.h
+++ b/arch/arm/mach-tegra/include/mach/io.h
@@ -65,8 +65,8 @@
 
 #ifndef __ASSEMBLER__
 
-#define __arch_ioremap(p, s, t)	tegra_ioremap(p, s, t)
-#define __arch_iounmap(v)	tegra_iounmap(v)
+#define __arch_ioremap		tegra_ioremap
+#define __arch_iounmap		tegra_iounmap
 
 void __iomem *tegra_ioremap(unsigned long phys, size_t size, unsigned int type);
 void tegra_iounmap(volatile void __iomem *addr);
diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c
index 50a8dfb..5407de0 100644
--- a/arch/arm/mach-tegra/irq.c
+++ b/arch/arm/mach-tegra/irq.c
@@ -94,8 +94,8 @@
 		writel(0, ictlr_to_virt(i) + ICTLR_CPU_IEP_CLASS);
 	}
 
-	gic_dist_init(0, IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE), 29);
-	gic_cpu_init(0, IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100));
+	gic_init(0, 29, IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE),
+		 IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100));
 
 	gic = get_irq_chip(29);
 	gic_unmask_irq = gic->unmask;
diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c
index 1c0fd92..3b7376c 100644
--- a/arch/arm/mach-tegra/platsmp.c
+++ b/arch/arm/mach-tegra/platsmp.c
@@ -48,7 +48,7 @@
 	 * core (e.g. timer irq), then they will not have been enabled
 	 * for us: do so
 	 */
-	gic_cpu_init(0, IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x100);
+	gic_secondary_init(0);
 
 	/*
 	 * Synchronise with the boot thread.
diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c
index 608a137..7328c01 100644
--- a/arch/arm/mach-ux500/cpu.c
+++ b/arch/arm/mach-ux500/cpu.c
@@ -61,8 +61,8 @@
 
 void __init ux500_init_irq(void)
 {
-	gic_dist_init(0, __io_address(UX500_GIC_DIST_BASE), 29);
-	gic_cpu_init(0, __io_address(UX500_GIC_CPU_BASE));
+	gic_init(0, 29, __io_address(UX500_GIC_DIST_BASE),
+		 __io_address(UX500_GIC_CPU_BASE));
 
 	/*
 	 * Init clocks here so that they are available for system timer
diff --git a/arch/arm/mach-ux500/include/mach/entry-macro.S b/arch/arm/mach-ux500/include/mach/entry-macro.S
index 60ea88d..a37f585 100644
--- a/arch/arm/mach-ux500/include/mach/entry-macro.S
+++ b/arch/arm/mach-ux500/include/mach/entry-macro.S
@@ -11,7 +11,8 @@
  * warranty of any kind, whether express or implied.
  */
 #include <mach/hardware.h>
-#include <asm/hardware/gic.h>
+#define HAVE_GET_IRQNR_PREAMBLE
+#include <asm/hardware/entry-macro-gic.S>
 
 		.macro	disable_fiq
 		.endm
@@ -22,68 +23,3 @@
 
 		.macro  arch_ret_to_user, tmp1, tmp2
 		.endm
-
-		/*
-		 * The interrupt numbering scheme is defined in the
-		 * interrupt controller spec.  To wit:
-		 *
-		 * Interrupts 0-15 are IPI
-		 * 16-28 are reserved
-		 * 29-31 are local.  We allow 30 to be used for the watchdog.
-		 * 32-1020 are global
-		 * 1021-1022 are reserved
-		 * 1023 is "spurious" (no interrupt)
-		 *
-		 * For now, we ignore all local interrupts so only return an
-		 * interrupt if it's between 30 and 1020. The test_for_ipi
-		 * routine below will pick up on IPIs.
-		 *
-		 * A simple read from the controller will tell us the number
-		 * of the highest priority enabled interrupt. We then just
-		 * need to check whether it is in the valid range for an
-		 * IRQ (30-1020 inclusive).
-		 */
-
-		.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-
-		/* bits 12-10 = src CPU, 9-0 = int # */
-		ldr     \irqstat, [\base, #GIC_CPU_INTACK]
-
-		ldr	\tmp, =1021
-
-		bic     \irqnr, \irqstat, #0x1c00
-
-		cmp     \irqnr, #29
-		cmpcc	\irqnr, \irqnr
-		cmpne	\irqnr, \tmp
-		cmpcs	\irqnr, \irqnr
-
-		.endm
-
-		/* We assume that irqstat (the raw value of the IRQ
-		 * acknowledge register) is preserved from the macro above.
-		 * If there is an IPI, we immediately signal end of
-		 * interrupt on the controller, since this requires the
-		 * original irqstat value which we won't easily be able
-		 * to recreate later.
-		 */
-
-		.macro test_for_ipi, irqnr, irqstat, base, tmp
-		bic	\irqnr, \irqstat, #0x1c00
-		cmp	\irqnr, #16
-		strcc	\irqstat, [\base, #GIC_CPU_EOI]
-		cmpcs	\irqnr, \irqnr
-		.endm
-
-		/* As above, this assumes that irqstat and base
-		 * are preserved..
-		 */
-
-		.macro test_for_ltirq, irqnr, irqstat, base, tmp
-		bic	\irqnr, \irqstat, #0x1c00
-		mov 	\tmp, #0
-		cmp	\irqnr, #29
-		moveq	\tmp, #1
-		streq	\irqstat, [\base, #GIC_CPU_EOI]
-		cmp	\tmp, #0
-		.endm
diff --git a/arch/arm/mach-ux500/platsmp.c b/arch/arm/mach-ux500/platsmp.c
index 9e4c678..b5077b4 100644
--- a/arch/arm/mach-ux500/platsmp.c
+++ b/arch/arm/mach-ux500/platsmp.c
@@ -44,7 +44,7 @@
 	 * core (e.g. timer irq), then they will not have been enabled
 	 * for us: do so
 	 */
-	gic_cpu_init(0, __io_address(UX500_GIC_CPU_BASE));
+	gic_secondary_init(0);
 
 	/*
 	 * let the primary processor know we're out of the
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
index e38acb0..6b93bd6 100644
--- a/arch/arm/mach-versatile/core.c
+++ b/arch/arm/mach-versatile/core.c
@@ -49,7 +49,7 @@
 #include <mach/clkdev.h>
 #include <mach/hardware.h>
 #include <mach/platform.h>
-#include <plat/timer-sp.h>
+#include <asm/hardware/timer-sp.h>
 
 #include "core.h"
 
diff --git a/arch/arm/mach-vexpress/core.h b/arch/arm/mach-vexpress/core.h
index 57dd95c..362780d 100644
--- a/arch/arm/mach-vexpress/core.h
+++ b/arch/arm/mach-vexpress/core.h
@@ -22,5 +22,3 @@
 
 void v2m_map_io(struct map_desc *tile, size_t num);
 extern struct sys_timer v2m_timer;
-
-extern void __iomem *gic_cpu_base_addr;
diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c
index fd25ccd..cb5793e 100644
--- a/arch/arm/mach-vexpress/ct-ca9x4.c
+++ b/arch/arm/mach-vexpress/ct-ca9x4.c
@@ -21,7 +21,7 @@
 #include <mach/clkdev.h>
 #include <mach/ct-ca9x4.h>
 
-#include <plat/timer-sp.h>
+#include <asm/hardware/timer-sp.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -60,13 +60,10 @@
 	v2m_map_io(ct_ca9x4_io_desc, ARRAY_SIZE(ct_ca9x4_io_desc));
 }
 
-void __iomem *gic_cpu_base_addr;
-
 static void __init ct_ca9x4_init_irq(void)
 {
-	gic_cpu_base_addr = MMIO_P2V(A9_MPCORE_GIC_CPU);
-	gic_dist_init(0, MMIO_P2V(A9_MPCORE_GIC_DIST), 29);
-	gic_cpu_init(0, gic_cpu_base_addr);
+	gic_init(0, 29, MMIO_P2V(A9_MPCORE_GIC_DIST),
+		 MMIO_P2V(A9_MPCORE_GIC_CPU));
 }
 
 #if 0
diff --git a/arch/arm/mach-vexpress/include/mach/entry-macro.S b/arch/arm/mach-vexpress/include/mach/entry-macro.S
index 20e9fb5..73c1129 100644
--- a/arch/arm/mach-vexpress/include/mach/entry-macro.S
+++ b/arch/arm/mach-vexpress/include/mach/entry-macro.S
@@ -1,67 +1,7 @@
-#include <asm/hardware/gic.h>
+#include <asm/hardware/entry-macro-gic.S>
 
 	.macro	disable_fiq
 	.endm
 
-	.macro	get_irqnr_preamble, base, tmp
-	ldr	\base, =gic_cpu_base_addr
-	ldr	\base, [\base]
-	.endm
-
 	.macro	arch_ret_to_user, tmp1, tmp2
 	.endm
-
-	/*
-	 * The interrupt numbering scheme is defined in the
-	 * interrupt controller spec.  To wit:
-	 *
-	 * Interrupts 0-15 are IPI
-	 * 16-28 are reserved
-	 * 29-31 are local.  We allow 30 to be used for the watchdog.
-	 * 32-1020 are global
-	 * 1021-1022 are reserved
-	 * 1023 is "spurious" (no interrupt)
-	 *
-	 * For now, we ignore all local interrupts so only return an interrupt if it's
-	 * between 30 and 1020.  The test_for_ipi routine below will pick up on IPIs.
-	 *
-	 * A simple read from the controller will tell us the number of the highest
-	 * priority enabled interrupt.  We then just need to check whether it is in the
-	 * valid range for an IRQ (30-1020 inclusive).
-	 */
-
-	.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
-	ldr     \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 = src CPU, 9-0 = int # */
-	ldr	\tmp, =1021
-	bic     \irqnr, \irqstat, #0x1c00
-	cmp     \irqnr, #29
-	cmpcc	\irqnr, \irqnr
-	cmpne	\irqnr, \tmp
-	cmpcs	\irqnr, \irqnr
-	.endm
-
-	/* We assume that irqstat (the raw value of the IRQ acknowledge
-	 * register) is preserved from the macro above.
-	 * If there is an IPI, we immediately signal end of interrupt on the
-	 * controller, since this requires the original irqstat value which
-	 * we won't easily be able to recreate later.
-	 */
-
-	.macro test_for_ipi, irqnr, irqstat, base, tmp
-	bic	\irqnr, \irqstat, #0x1c00
-	cmp	\irqnr, #16
-	strcc	\irqstat, [\base, #GIC_CPU_EOI]
-	cmpcs	\irqnr, \irqnr
-	.endm
-
-	/* As above, this assumes that irqstat and base are preserved.. */
-
-	.macro test_for_ltirq, irqnr, irqstat, base, tmp
-	bic	\irqnr, \irqstat, #0x1c00
-	mov 	\tmp, #0
-	cmp	\irqnr, #29
-	moveq	\tmp, #1
-	streq	\irqstat, [\base, #GIC_CPU_EOI]
-	cmp	\tmp, #0
-	.endm
-
diff --git a/arch/arm/mach-vexpress/platsmp.c b/arch/arm/mach-vexpress/platsmp.c
index 6709706..dfb5910 100644
--- a/arch/arm/mach-vexpress/platsmp.c
+++ b/arch/arm/mach-vexpress/platsmp.c
@@ -51,7 +51,7 @@
 	 * core (e.g. timer irq), then they will not have been enabled
 	 * for us: do so
 	 */
-	gic_cpu_init(0, gic_cpu_base_addr);
+	gic_secondary_init(0);
 
 	/*
 	 * let the primary processor know we're out of the
diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c
index 7eaa232..91ff2e0 100644
--- a/arch/arm/mach-vexpress/v2m.c
+++ b/arch/arm/mach-vexpress/v2m.c
@@ -22,7 +22,7 @@
 #include <mach/clkdev.h>
 #include <mach/motherboard.h>
 
-#include <plat/timer-sp.h>
+#include <asm/hardware/timer-sp.h>
 
 #include "core.h"
 
diff --git a/arch/arm/plat-omap/include/plat/io.h b/arch/arm/plat-omap/include/plat/io.h
index 128b549..204865f 100644
--- a/arch/arm/plat-omap/include/plat/io.h
+++ b/arch/arm/plat-omap/include/plat/io.h
@@ -294,8 +294,8 @@
 extern void omap2_init_common_hw(struct omap_sdrc_params *sdrc_cs0,
 				 struct omap_sdrc_params *sdrc_cs1);
 
-#define __arch_ioremap(p,s,t)	omap_ioremap(p,s,t)
-#define __arch_iounmap(v)	omap_iounmap(v)
+#define __arch_ioremap	omap_ioremap
+#define __arch_iounmap	omap_iounmap
 
 void __iomem *omap_ioremap(unsigned long phys, size_t size, unsigned int type);
 void omap_iounmap(volatile void __iomem *addr);
diff --git a/arch/arm/plat-versatile/Makefile b/arch/arm/plat-versatile/Makefile
index 5cf88e8..aaa571d 100644
--- a/arch/arm/plat-versatile/Makefile
+++ b/arch/arm/plat-versatile/Makefile
@@ -1,5 +1,4 @@
 obj-y	:= clock.o
-obj-$(CONFIG_ARM_TIMER_SP804) += timer-sp.o
 obj-$(CONFIG_ARCH_REALVIEW) += sched-clock.o
 obj-$(CONFIG_ARCH_VERSATILE) += sched-clock.o
 ifeq ($(CONFIG_LEDS_CLASS),y)
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile
index 8d9386a..a565300 100644
--- a/drivers/pcmcia/Makefile
+++ b/drivers/pcmcia/Makefile
@@ -50,8 +50,9 @@
 sa1100_cs-y					+= sa1100_generic.o
 sa1100_cs-$(CONFIG_SA1100_ASSABET)		+= sa1100_assabet.o
 sa1100_cs-$(CONFIG_SA1100_CERF)			+= sa1100_cerf.o
-sa1100_cs-$(CONFIG_SA1100_COLLIE)              += pxa2xx_sharpsl.o
+sa1100_cs-$(CONFIG_SA1100_COLLIE)		+= pxa2xx_sharpsl.o
 sa1100_cs-$(CONFIG_SA1100_H3600)		+= sa1100_h3600.o
+sa1100_cs-$(CONFIG_SA1100_NANOENGINE)		+= sa1100_nanoengine.o
 sa1100_cs-$(CONFIG_SA1100_SHANNON)		+= sa1100_shannon.o
 sa1100_cs-$(CONFIG_SA1100_SIMPAD)		+= sa1100_simpad.o
 
diff --git a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c
index 6b22859..fb9740d 100644
--- a/drivers/pcmcia/sa1100_generic.c
+++ b/drivers/pcmcia/sa1100_generic.c
@@ -53,6 +53,9 @@
 #if defined(CONFIG_SA1100_H3100) || defined(CONFIG_SA1100_H3600)
 	pcmcia_h3600_init,
 #endif
+#ifdef CONFIG_SA1100_NANOENGINE
+	pcmcia_nanoengine_init,
+#endif
 #ifdef CONFIG_SA1100_SHANNON
 	pcmcia_shannon_init,
 #endif
diff --git a/drivers/pcmcia/sa1100_generic.h b/drivers/pcmcia/sa1100_generic.h
index 794f96a..adb08db 100644
--- a/drivers/pcmcia/sa1100_generic.h
+++ b/drivers/pcmcia/sa1100_generic.h
@@ -13,6 +13,7 @@
 extern int pcmcia_gcplus_init(struct device *);
 extern int pcmcia_graphicsmaster_init(struct device *);
 extern int pcmcia_h3600_init(struct device *);
+extern int pcmcia_nanoengine_init(struct device *);
 extern int pcmcia_pangolin_init(struct device *);
 extern int pcmcia_pfs168_init(struct device *);
 extern int pcmcia_shannon_init(struct device *);
diff --git a/drivers/pcmcia/sa1100_nanoengine.c b/drivers/pcmcia/sa1100_nanoengine.c
new file mode 100644
index 0000000..3d2652e
--- /dev/null
+++ b/drivers/pcmcia/sa1100_nanoengine.c
@@ -0,0 +1,219 @@
+/*
+ * drivers/pcmcia/sa1100_nanoengine.c
+ *
+ * PCMCIA implementation routines for BSI nanoEngine.
+ *
+ * In order to have a fully functional pcmcia subsystem in a BSE nanoEngine
+ * board you should carefully read this:
+ * http://cambuca.ldhs.cetuc.puc-rio.br/nanoengine/
+ *
+ * Copyright (C) 2010 Marcelo Roberto Jimenez <mroberto@cpti.cetuc.puc-rio.br>
+ *
+ * Based on original work for kernel 2.4 by
+ * Miguel Freitas <miguel@cpti.cetuc.puc-rio.br>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/nanoengine.h>
+
+#include "sa1100_generic.h"
+
+static struct pcmcia_irqs irqs_skt0[] = {
+	/* socket, IRQ, name */
+	{ 0, NANOENGINE_IRQ_GPIO_PC_CD0, "PC CD0" },
+};
+
+static struct pcmcia_irqs irqs_skt1[] = {
+	/* socket, IRQ, name */
+	{ 1, NANOENGINE_IRQ_GPIO_PC_CD1, "PC CD1" },
+};
+
+struct nanoengine_pins {
+	unsigned input_pins;
+	unsigned output_pins;
+	unsigned clear_outputs;
+	unsigned transition_pins;
+	unsigned pci_irq;
+	struct pcmcia_irqs *pcmcia_irqs;
+	unsigned pcmcia_irqs_size;
+};
+
+static struct nanoengine_pins nano_skts[] = {
+	{
+		.input_pins		= GPIO_PC_READY0 | GPIO_PC_CD0,
+		.output_pins		= GPIO_PC_RESET0,
+		.clear_outputs		= GPIO_PC_RESET0,
+		.transition_pins	= NANOENGINE_IRQ_GPIO_PC_CD0,
+		.pci_irq		= NANOENGINE_IRQ_GPIO_PC_READY0,
+		.pcmcia_irqs		= irqs_skt0,
+		.pcmcia_irqs_size	= ARRAY_SIZE(irqs_skt0)
+	}, {
+		.input_pins		= GPIO_PC_READY1 | GPIO_PC_CD1,
+		.output_pins		= GPIO_PC_RESET1,
+		.clear_outputs		= GPIO_PC_RESET1,
+		.transition_pins	= NANOENGINE_IRQ_GPIO_PC_CD1,
+		.pci_irq		= NANOENGINE_IRQ_GPIO_PC_READY1,
+		.pcmcia_irqs		= irqs_skt1,
+		.pcmcia_irqs_size	= ARRAY_SIZE(irqs_skt1)
+	}
+};
+
+unsigned num_nano_pcmcia_sockets = ARRAY_SIZE(nano_skts);
+
+static int nanoengine_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
+{
+	unsigned i = skt->nr;
+
+	if (i >= num_nano_pcmcia_sockets)
+		return -ENXIO;
+
+	GPDR &= ~nano_skts[i].input_pins;
+	GPDR |= nano_skts[i].output_pins;
+	GPCR = nano_skts[i].clear_outputs;
+	set_irq_type(nano_skts[i].transition_pins, IRQ_TYPE_EDGE_BOTH);
+	skt->socket.pci_irq = nano_skts[i].pci_irq;
+
+	return soc_pcmcia_request_irqs(skt,
+		nano_skts[i].pcmcia_irqs, nano_skts[i].pcmcia_irqs_size);
+}
+
+/*
+ * Release all resources.
+ */
+static void nanoengine_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
+{
+	unsigned i = skt->nr;
+
+	if (i >= num_nano_pcmcia_sockets)
+		return;
+
+	soc_pcmcia_free_irqs(skt,
+		nano_skts[i].pcmcia_irqs, nano_skts[i].pcmcia_irqs_size);
+}
+
+static int nanoengine_pcmcia_configure_socket(
+	struct soc_pcmcia_socket *skt, const socket_state_t *state)
+{
+	unsigned reset;
+	unsigned i = skt->nr;
+
+	if (i >= num_nano_pcmcia_sockets)
+		return -ENXIO;
+
+	switch (i) {
+	case 0:
+		reset = GPIO_PC_RESET0;
+		break;
+	case 1:
+		reset = GPIO_PC_RESET1;
+		break;
+	default:
+		return -ENXIO;
+	}
+
+	if (state->flags & SS_RESET)
+		GPSR = reset;
+	else
+		GPCR = reset;
+
+	return 0;
+}
+
+static void nanoengine_pcmcia_socket_state(
+	struct soc_pcmcia_socket *skt, struct pcmcia_state *state)
+{
+	unsigned long levels = GPLR;
+	unsigned i = skt->nr;
+
+	if (i >= num_nano_pcmcia_sockets)
+		return;
+
+	memset(state, 0, sizeof(struct pcmcia_state));
+	switch (i) {
+	case 0:
+		state->ready = (levels & GPIO_PC_READY0) ? 1 : 0;
+		state->detect = !(levels & GPIO_PC_CD0) ? 1 : 0;
+		break;
+	case 1:
+		state->ready = (levels & GPIO_PC_READY1) ? 1 : 0;
+		state->detect = !(levels & GPIO_PC_CD1) ? 1 : 0;
+		break;
+	default:
+		return;
+	}
+	state->bvd1 = 1;
+	state->bvd2 = 1;
+	state->wrprot = 0; /* Not available */
+	state->vs_3v = 1; /* Can only apply 3.3V */
+	state->vs_Xv = 0;
+}
+
+/*
+ * Enable card status IRQs on (re-)initialisation.  This can
+ * be called at initialisation, power management event, or
+ * pcmcia event.
+ */
+static void nanoengine_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
+{
+	unsigned i = skt->nr;
+
+	if (i >= num_nano_pcmcia_sockets)
+		return;
+
+	soc_pcmcia_enable_irqs(skt,
+		nano_skts[i].pcmcia_irqs, nano_skts[i].pcmcia_irqs_size);
+}
+
+/*
+ * Disable card status IRQs on suspend.
+ */
+static void nanoengine_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
+{
+	unsigned i = skt->nr;
+
+	if (i >= num_nano_pcmcia_sockets)
+		return;
+
+	soc_pcmcia_disable_irqs(skt,
+		nano_skts[i].pcmcia_irqs, nano_skts[i].pcmcia_irqs_size);
+}
+
+static struct pcmcia_low_level nanoengine_pcmcia_ops = {
+	.owner			= THIS_MODULE,
+
+	.hw_init		= nanoengine_pcmcia_hw_init,
+	.hw_shutdown		= nanoengine_pcmcia_hw_shutdown,
+
+	.configure_socket	= nanoengine_pcmcia_configure_socket,
+	.socket_state		= nanoengine_pcmcia_socket_state,
+	.socket_init		= nanoengine_pcmcia_socket_init,
+	.socket_suspend		= nanoengine_pcmcia_socket_suspend,
+};
+
+int pcmcia_nanoengine_init(struct device *dev)
+{
+	int ret = -ENODEV;
+
+	if (machine_is_nanoengine())
+		ret = sa11xx_drv_pcmcia_probe(
+			dev, &nanoengine_pcmcia_ops, 0, 2);
+
+	return ret;
+}
+
diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c
index 2fe8cb8..5a9a392 100644
--- a/drivers/pcmcia/soc_common.c
+++ b/drivers/pcmcia/soc_common.c
@@ -31,20 +31,20 @@
 ======================================================================*/
 
 
+#include <linux/cpufreq.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
 #include <linux/mutex.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
 #include <linux/spinlock.h>
-#include <linux/cpufreq.h>
+#include <linux/timer.h>
 
 #include <mach/hardware.h>
-#include <asm/io.h>
 #include <asm/system.h>
 
 #include "soc_common.h"
@@ -74,7 +74,8 @@
 
 #endif
 
-#define to_soc_pcmcia_socket(x)	container_of(x, struct soc_pcmcia_socket, socket)
+#define to_soc_pcmcia_socket(x)	\
+	container_of(x, struct soc_pcmcia_socket, socket)
 
 static unsigned short
 calc_speed(unsigned short *spds, int num, unsigned short dflt)
@@ -91,11 +92,15 @@
 	return speed;
 }
 
-void soc_common_pcmcia_get_timing(struct soc_pcmcia_socket *skt, struct soc_pcmcia_timing *timing)
+void soc_common_pcmcia_get_timing(struct soc_pcmcia_socket *skt,
+	struct soc_pcmcia_timing *timing)
 {
-	timing->io = calc_speed(skt->spd_io, MAX_IO_WIN, SOC_PCMCIA_IO_ACCESS);
-	timing->mem = calc_speed(skt->spd_mem, MAX_WIN, SOC_PCMCIA_3V_MEM_ACCESS);
-	timing->attr = calc_speed(skt->spd_attr, MAX_WIN, SOC_PCMCIA_3V_MEM_ACCESS);
+	timing->io =
+		calc_speed(skt->spd_io, MAX_IO_WIN, SOC_PCMCIA_IO_ACCESS);
+	timing->mem =
+		calc_speed(skt->spd_mem, MAX_WIN, SOC_PCMCIA_3V_MEM_ACCESS);
+	timing->attr =
+		calc_speed(skt->spd_attr, MAX_WIN, SOC_PCMCIA_3V_MEM_ACCESS);
 }
 EXPORT_SYMBOL(soc_common_pcmcia_get_timing);
 
@@ -137,8 +142,8 @@
  *
  * Convert PCMCIA socket state to our socket configure structure.
  */
-static int
-soc_common_pcmcia_config_skt(struct soc_pcmcia_socket *skt, socket_state_t *state)
+static int soc_common_pcmcia_config_skt(
+	struct soc_pcmcia_socket *skt, socket_state_t *state)
 {
 	int ret;
 
@@ -150,7 +155,8 @@
 		 */
 		if (skt->irq_state != 1 && state->io_irq) {
 			skt->irq_state = 1;
-			set_irq_type(skt->socket.pci_irq, IRQ_TYPE_EDGE_FALLING);
+			set_irq_type(skt->socket.pci_irq,
+				IRQ_TYPE_EDGE_FALLING);
 		} else if (skt->irq_state == 1 && state->io_irq == 0) {
 			skt->irq_state = 0;
 			set_irq_type(skt->socket.pci_irq, IRQ_TYPE_NONE);
@@ -304,24 +310,24 @@
  * of power configuration, reset, &c. We also record the value of
  * `state' in order to regurgitate it to the PCMCIA core later.
  */
-static int
-soc_common_pcmcia_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
+static int soc_common_pcmcia_set_socket(
+	struct pcmcia_socket *sock, socket_state_t *state)
 {
 	struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock);
 
-	debug(skt, 2, "mask: %s%s%s%s%s%sflags: %s%s%s%s%s%sVcc %d Vpp %d irq %d\n",
-			(state->csc_mask==0)?"<NONE> ":"",
-			(state->csc_mask&SS_DETECT)?"DETECT ":"",
-			(state->csc_mask&SS_READY)?"READY ":"",
-			(state->csc_mask&SS_BATDEAD)?"BATDEAD ":"",
-			(state->csc_mask&SS_BATWARN)?"BATWARN ":"",
-			(state->csc_mask&SS_STSCHG)?"STSCHG ":"",
-			(state->flags==0)?"<NONE> ":"",
-			(state->flags&SS_PWR_AUTO)?"PWR_AUTO ":"",
-			(state->flags&SS_IOCARD)?"IOCARD ":"",
-			(state->flags&SS_RESET)?"RESET ":"",
-			(state->flags&SS_SPKR_ENA)?"SPKR_ENA ":"",
-			(state->flags&SS_OUTPUT_ENA)?"OUTPUT_ENA ":"",
+	debug(skt, 2, "mask: %s%s%s%s%s%s flags: %s%s%s%s%s%s Vcc %d Vpp %d irq %d\n",
+			(state->csc_mask == 0)		? "<NONE> " :	"",
+			(state->csc_mask & SS_DETECT)	? "DETECT " :	"",
+			(state->csc_mask & SS_READY)	? "READY " :	"",
+			(state->csc_mask & SS_BATDEAD)	? "BATDEAD " :	"",
+			(state->csc_mask & SS_BATWARN)	? "BATWARN " :	"",
+			(state->csc_mask & SS_STSCHG)	? "STSCHG " :	"",
+			(state->flags == 0)		? "<NONE> " :	"",
+			(state->flags & SS_PWR_AUTO)	? "PWR_AUTO " :	"",
+			(state->flags & SS_IOCARD)	? "IOCARD " :	"",
+			(state->flags & SS_RESET)	? "RESET " :	"",
+			(state->flags & SS_SPKR_ENA)	? "SPKR_ENA " :	"",
+			(state->flags & SS_OUTPUT_ENA)	? "OUTPUT_ENA " : "",
 			state->Vcc, state->Vpp, state->io_irq);
 
 	return soc_common_pcmcia_config_skt(skt, state);
@@ -336,8 +342,8 @@
  *
  * Returns: 0 on success, -1 on error
  */
-static int
-soc_common_pcmcia_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *map)
+static int soc_common_pcmcia_set_io_map(
+	struct pcmcia_socket *sock, struct pccard_io_map *map)
 {
 	struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock);
 	unsigned short speed = map->speed;
@@ -346,14 +352,14 @@
 		map->map, map->speed, (unsigned long long)map->start,
 		(unsigned long long)map->stop);
 	debug(skt, 2, "flags: %s%s%s%s%s%s%s%s\n",
-		(map->flags==0)?"<NONE>":"",
-		(map->flags&MAP_ACTIVE)?"ACTIVE ":"",
-		(map->flags&MAP_16BIT)?"16BIT ":"",
-		(map->flags&MAP_AUTOSZ)?"AUTOSZ ":"",
-		(map->flags&MAP_0WS)?"0WS ":"",
-		(map->flags&MAP_WRPROT)?"WRPROT ":"",
-		(map->flags&MAP_USE_WAIT)?"USE_WAIT ":"",
-		(map->flags&MAP_PREFETCH)?"PREFETCH ":"");
+		(map->flags == 0)		? "<NONE>"	: "",
+		(map->flags & MAP_ACTIVE)	? "ACTIVE "	: "",
+		(map->flags & MAP_16BIT)	? "16BIT "	: "",
+		(map->flags & MAP_AUTOSZ)	? "AUTOSZ "	: "",
+		(map->flags & MAP_0WS)		? "0WS "	: "",
+		(map->flags & MAP_WRPROT)	? "WRPROT "	: "",
+		(map->flags & MAP_USE_WAIT)	? "USE_WAIT "	: "",
+		(map->flags & MAP_PREFETCH)	? "PREFETCH "	: "");
 
 	if (map->map >= MAX_IO_WIN) {
 		printk(KERN_ERR "%s(): map (%d) out of range\n", __func__,
@@ -390,8 +396,8 @@
  *
  * Returns: 0 on success, -ERRNO on error
  */
-static int
-soc_common_pcmcia_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *map)
+static int soc_common_pcmcia_set_mem_map(
+	struct pcmcia_socket *sock, struct pccard_mem_map *map)
 {
 	struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock);
 	struct resource *res;
@@ -400,14 +406,14 @@
 	debug(skt, 2, "map %u speed %u card_start %08x\n",
 		map->map, map->speed, map->card_start);
 	debug(skt, 2, "flags: %s%s%s%s%s%s%s%s\n",
-		(map->flags==0)?"<NONE>":"",
-		(map->flags&MAP_ACTIVE)?"ACTIVE ":"",
-		(map->flags&MAP_16BIT)?"16BIT ":"",
-		(map->flags&MAP_AUTOSZ)?"AUTOSZ ":"",
-		(map->flags&MAP_0WS)?"0WS ":"",
-		(map->flags&MAP_WRPROT)?"WRPROT ":"",
-		(map->flags&MAP_ATTRIB)?"ATTRIB ":"",
-		(map->flags&MAP_USE_WAIT)?"USE_WAIT ":"");
+		(map->flags == 0)		? "<NONE>"	: "",
+		(map->flags & MAP_ACTIVE)	? "ACTIVE "	: "",
+		(map->flags & MAP_16BIT)	? "16BIT "	: "",
+		(map->flags & MAP_AUTOSZ)	? "AUTOSZ "	: "",
+		(map->flags & MAP_0WS)		? "0WS "	: "",
+		(map->flags & MAP_WRPROT)	? "WRPROT "	: "",
+		(map->flags & MAP_ATTRIB)	? "ATTRIB "	: "",
+		(map->flags & MAP_USE_WAIT)	? "USE_WAIT "	: "");
 
 	if (map->map >= MAX_WIN)
 		return -EINVAL;
@@ -462,8 +468,8 @@
 	{ SS_OUTPUT_ENA,	"SS_OUTPUT_ENA"	},
 };
 
-static void
-dump_bits(char **p, const char *prefix, unsigned int val, struct bittbl *bits, int sz)
+static void dump_bits(char **p, const char *prefix,
+	unsigned int val, struct bittbl *bits, int sz)
 {
 	char *b = *p;
 	int i;
@@ -481,13 +487,14 @@
  *
  * Returns: the number of characters added to the buffer
  */
-static ssize_t show_status(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_status(
+	struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct soc_pcmcia_socket *skt =
 		container_of(dev, struct soc_pcmcia_socket, socket.dev);
 	char *p = buf;
 
-	p+=sprintf(p, "slot     : %d\n", skt->nr);
+	p += sprintf(p, "slot     : %d\n", skt->nr);
 
 	dump_bits(&p, "status", skt->status,
 		  status_bits, ARRAY_SIZE(status_bits));
@@ -496,12 +503,12 @@
 	dump_bits(&p, "cs_flags", skt->cs_state.flags,
 		  conf_bits, ARRAY_SIZE(conf_bits));
 
-	p+=sprintf(p, "Vcc      : %d\n", skt->cs_state.Vcc);
-	p+=sprintf(p, "Vpp      : %d\n", skt->cs_state.Vpp);
-	p+=sprintf(p, "IRQ      : %d (%d)\n", skt->cs_state.io_irq,
+	p += sprintf(p, "Vcc      : %d\n", skt->cs_state.Vcc);
+	p += sprintf(p, "Vpp      : %d\n", skt->cs_state.Vpp);
+	p += sprintf(p, "IRQ      : %d (%d)\n", skt->cs_state.io_irq,
 		skt->socket.pci_irq);
 	if (skt->ops->show_timing)
-		p+=skt->ops->show_timing(skt, p);
+		p += skt->ops->show_timing(skt, p);
 
 	return p-buf;
 }
@@ -594,7 +601,7 @@
 
 	mutex_lock(&soc_pcmcia_sockets_lock);
 	list_for_each_entry(skt, &soc_pcmcia_sockets, node)
-		if ( skt->ops->frequency_change )
+		if (skt->ops->frequency_change)
 			ret += skt->ops->frequency_change(skt, val, freqs);
 	mutex_unlock(&soc_pcmcia_sockets_lock);
 
@@ -620,7 +627,8 @@
 
 static void soc_pcmcia_cpufreq_unregister(void)
 {
-	cpufreq_unregister_notifier(&soc_pcmcia_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
+	cpufreq_unregister_notifier(&soc_pcmcia_notifier_block,
+		CPUFREQ_TRANSITION_NOTIFIER);
 }
 module_exit(soc_pcmcia_cpufreq_unregister);
 
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c
index e4a44b6..88ea52b 100644
--- a/drivers/rtc/rtc-sa1100.c
+++ b/drivers/rtc/rtc-sa1100.c
@@ -39,10 +39,10 @@
 #include <mach/regs-ost.h>
 #endif
 
-#define RTC_DEF_DIVIDER		32768 - 1
+#define RTC_DEF_DIVIDER		(32768 - 1)
 #define RTC_DEF_TRIM		0
 
-static unsigned long rtc_freq = 1024;
+static const unsigned long RTC_FREQ = 1024;
 static unsigned long timer_freq;
 static struct rtc_time rtc_alarm;
 static DEFINE_SPINLOCK(sa1100_rtc_lock);
@@ -61,7 +61,8 @@
  * Calculate the next alarm time given the requested alarm time mask
  * and the current time.
  */
-static void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now, struct rtc_time *alrm)
+static void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now,
+	struct rtc_time *alrm)
 {
 	unsigned long next_time;
 	unsigned long now_time;
@@ -116,7 +117,23 @@
 	rtsr = RTSR;
 	/* clear interrupt sources */
 	RTSR = 0;
-	RTSR = (RTSR_AL | RTSR_HZ) & (rtsr >> 2);
+	/* Fix for a nasty initialization problem the in SA11xx RTSR register.
+	 * See also the comments in sa1100_rtc_probe(). */
+	if (rtsr & (RTSR_ALE | RTSR_HZE)) {
+		/* This is the original code, before there was the if test
+		 * above. This code does not clear interrupts that were not
+		 * enabled. */
+		RTSR = (RTSR_AL | RTSR_HZ) & (rtsr >> 2);
+	} else {
+		/* For some reason, it is possible to enter this routine
+		 * without interruptions enabled, it has been tested with
+		 * several units (Bug in SA11xx chip?).
+		 *
+		 * This situation leads to an infinite "loop" of interrupt
+		 * routine calling and as a result the processor seems to
+		 * lock on its first call to open(). */
+		RTSR = RTSR_AL | RTSR_HZ;
+	}
 
 	/* clear alarm interrupt if it has occurred */
 	if (rtsr & RTSR_AL)
@@ -139,8 +156,58 @@
 	return IRQ_HANDLED;
 }
 
+static int sa1100_irq_set_freq(struct device *dev, int freq)
+{
+	if (freq < 1 || freq > timer_freq) {
+		return -EINVAL;
+	} else {
+		struct rtc_device *rtc = (struct rtc_device *)dev;
+
+		rtc->irq_freq = freq;
+
+		return 0;
+	}
+}
+
 static int rtc_timer1_count;
 
+static int sa1100_irq_set_state(struct device *dev, int enabled)
+{
+	spin_lock_irq(&sa1100_rtc_lock);
+	if (enabled) {
+		struct rtc_device *rtc = (struct rtc_device *)dev;
+
+		OSMR1 = timer_freq / rtc->irq_freq + OSCR;
+		OIER |= OIER_E1;
+		rtc_timer1_count = 1;
+	} else {
+		OIER &= ~OIER_E1;
+	}
+	spin_unlock_irq(&sa1100_rtc_lock);
+
+	return 0;
+}
+
+static inline int sa1100_timer1_retrigger(struct rtc_device *rtc)
+{
+	unsigned long diff;
+	unsigned long period = timer_freq / rtc->irq_freq;
+
+	spin_lock_irq(&sa1100_rtc_lock);
+
+	do {
+		OSMR1 += period;
+		diff = OSMR1 - OSCR;
+		/* If OSCR > OSMR1, diff is a very large number (unsigned
+		 * math). This means we have a lost interrupt. */
+	} while (diff > period);
+	OIER |= OIER_E1;
+
+	spin_unlock_irq(&sa1100_rtc_lock);
+
+	return 0;
+}
+
 static irqreturn_t timer1_interrupt(int irq, void *dev_id)
 {
 	struct platform_device *pdev = to_platform_device(dev_id);
@@ -158,7 +225,11 @@
 	rtc_update_irq(rtc, rtc_timer1_count, RTC_PF | RTC_IRQF);
 
 	if (rtc_timer1_count == 1)
-		rtc_timer1_count = (rtc_freq * ((1 << 30) / (timer_freq >> 2)));
+		rtc_timer1_count =
+			(rtc->irq_freq * ((1 << 30) / (timer_freq >> 2)));
+
+	/* retrigger. */
+	sa1100_timer1_retrigger(rtc);
 
 	return IRQ_HANDLED;
 }
@@ -166,8 +237,10 @@
 static int sa1100_rtc_read_callback(struct device *dev, int data)
 {
 	if (data & RTC_PF) {
+		struct rtc_device *rtc = (struct rtc_device *)dev;
+
 		/* interpolate missed periods and set match for the next */
-		unsigned long period = timer_freq / rtc_freq;
+		unsigned long period = timer_freq / rtc->irq_freq;
 		unsigned long oscr = OSCR;
 		unsigned long osmr1 = OSMR1;
 		unsigned long missed = (oscr - osmr1)/period;
@@ -178,7 +251,7 @@
 		 * Here we compare (match - OSCR) 8 instead of 0 --
 		 * see comment in pxa_timer_interrupt() for explanation.
 		 */
-		while( (signed long)((osmr1 = OSMR1) - OSCR) <= 8 ) {
+		while ((signed long)((osmr1 = OSMR1) - OSCR) <= 8) {
 			data += 0x100;
 			OSSR = OSSR_M1;	/* clear match on timer 1 */
 			OSMR1 = osmr1 + period;
@@ -190,25 +263,29 @@
 static int sa1100_rtc_open(struct device *dev)
 {
 	int ret;
+	struct rtc_device *rtc = (struct rtc_device *)dev;
 
 	ret = request_irq(IRQ_RTC1Hz, sa1100_rtc_interrupt, IRQF_DISABLED,
-				"rtc 1Hz", dev);
+		"rtc 1Hz", dev);
 	if (ret) {
 		dev_err(dev, "IRQ %d already in use.\n", IRQ_RTC1Hz);
 		goto fail_ui;
 	}
 	ret = request_irq(IRQ_RTCAlrm, sa1100_rtc_interrupt, IRQF_DISABLED,
-				"rtc Alrm", dev);
+		"rtc Alrm", dev);
 	if (ret) {
 		dev_err(dev, "IRQ %d already in use.\n", IRQ_RTCAlrm);
 		goto fail_ai;
 	}
 	ret = request_irq(IRQ_OST1, timer1_interrupt, IRQF_DISABLED,
-				"rtc timer", dev);
+		"rtc timer", dev);
 	if (ret) {
 		dev_err(dev, "IRQ %d already in use.\n", IRQ_OST1);
 		goto fail_pi;
 	}
+	rtc->max_user_freq = RTC_FREQ;
+	sa1100_irq_set_freq(dev, RTC_FREQ);
+
 	return 0;
 
  fail_pi:
@@ -236,7 +313,7 @@
 static int sa1100_rtc_ioctl(struct device *dev, unsigned int cmd,
 		unsigned long arg)
 {
-	switch(cmd) {
+	switch (cmd) {
 	case RTC_AIE_OFF:
 		spin_lock_irq(&sa1100_rtc_lock);
 		RTSR &= ~RTSR_ALE;
@@ -257,25 +334,6 @@
 		RTSR |= RTSR_HZE;
 		spin_unlock_irq(&sa1100_rtc_lock);
 		return 0;
-	case RTC_PIE_OFF:
-		spin_lock_irq(&sa1100_rtc_lock);
-		OIER &= ~OIER_E1;
-		spin_unlock_irq(&sa1100_rtc_lock);
-		return 0;
-	case RTC_PIE_ON:
-		spin_lock_irq(&sa1100_rtc_lock);
-		OSMR1 = timer_freq / rtc_freq + OSCR;
-		OIER |= OIER_E1;
-		rtc_timer1_count = 1;
-		spin_unlock_irq(&sa1100_rtc_lock);
-		return 0;
-	case RTC_IRQP_READ:
-		return put_user(rtc_freq, (unsigned long *)arg);
-	case RTC_IRQP_SET:
-		if (arg < 1 || arg > timer_freq)
-			return -EINVAL;
-		rtc_freq = arg;
-		return 0;
 	}
 	return -ENOIOCTLCMD;
 }
@@ -327,12 +385,15 @@
 
 static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq)
 {
+	struct rtc_device *rtc = (struct rtc_device *)dev;
+
 	seq_printf(seq, "trim/divider\t: 0x%08x\n", (u32) RTTR);
 	seq_printf(seq, "update_IRQ\t: %s\n",
 			(RTSR & RTSR_HZE) ? "yes" : "no");
 	seq_printf(seq, "periodic_IRQ\t: %s\n",
 			(OIER & OIER_E1) ? "yes" : "no");
-	seq_printf(seq, "periodic_freq\t: %ld\n", rtc_freq);
+	seq_printf(seq, "periodic_freq\t: %d\n", rtc->irq_freq);
+	seq_printf(seq, "RTSR\t\t: 0x%08x\n", (u32)RTSR);
 
 	return 0;
 }
@@ -347,6 +408,8 @@
 	.read_alarm = sa1100_rtc_read_alarm,
 	.set_alarm = sa1100_rtc_set_alarm,
 	.proc = sa1100_rtc_proc,
+	.irq_set_freq = sa1100_irq_set_freq,
+	.irq_set_state = sa1100_irq_set_state,
 };
 
 static int sa1100_rtc_probe(struct platform_device *pdev)
@@ -364,7 +427,8 @@
 	 */
 	if (RTTR == 0) {
 		RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16);
-		dev_warn(&pdev->dev, "warning: initializing default clock divider/trim value\n");
+		dev_warn(&pdev->dev, "warning: "
+			"initializing default clock divider/trim value\n");
 		/* The current RTC value probably doesn't make sense either */
 		RCNR = 0;
 	}
@@ -372,13 +436,42 @@
 	device_init_wakeup(&pdev->dev, 1);
 
 	rtc = rtc_device_register(pdev->name, &pdev->dev, &sa1100_rtc_ops,
-				THIS_MODULE);
+		THIS_MODULE);
 
 	if (IS_ERR(rtc))
 		return PTR_ERR(rtc);
 
 	platform_set_drvdata(pdev, rtc);
 
+	/* Set the irq_freq */
+	/*TODO: Find out who is messing with this value after we initialize
+	 * it here.*/
+	rtc->irq_freq = RTC_FREQ;
+
+	/* Fix for a nasty initialization problem the in SA11xx RTSR register.
+	 * See also the comments in sa1100_rtc_interrupt().
+	 *
+	 * Sometimes bit 1 of the RTSR (RTSR_HZ) will wake up 1, which means an
+	 * interrupt pending, even though interrupts were never enabled.
+	 * In this case, this bit it must be reset before enabling
+	 * interruptions to avoid a nonexistent interrupt to occur.
+	 *
+	 * In principle, the same problem would apply to bit 0, although it has
+	 * never been observed to happen.
+	 *
+	 * This issue is addressed both here and in sa1100_rtc_interrupt().
+	 * If the issue is not addressed here, in the times when the processor
+	 * wakes up with the bit set there will be one spurious interrupt.
+	 *
+	 * The issue is also dealt with in sa1100_rtc_interrupt() to be on the
+	 * safe side, once the condition that lead to this strange
+	 * initialization is unknown and could in principle happen during
+	 * normal processing.
+	 *
+	 * Notice that clearing bit 1 and 0 is accomplished by writting ONES to
+	 * the corresponding bits in RTSR. */
+	RTSR = RTSR_AL | RTSR_HZ;
+
 	return 0;
 }
 
@@ -386,7 +479,7 @@
 {
 	struct rtc_device *rtc = platform_get_drvdata(pdev);
 
- 	if (rtc)
+	if (rtc)
 		rtc_device_unregister(rtc);
 
 	return 0;
diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c
index 2367fb3..74802bc5 100644
--- a/fs/proc/vmcore.c
+++ b/fs/proc/vmcore.c
@@ -499,7 +499,7 @@
 	/* Do some basic Verification. */
 	if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0 ||
 		(ehdr.e_type != ET_CORE) ||
-		!vmcore_elf_check_arch(&ehdr) ||
+		!vmcore_elf64_check_arch(&ehdr) ||
 		ehdr.e_ident[EI_CLASS] != ELFCLASS64 ||
 		ehdr.e_ident[EI_VERSION] != EV_CURRENT ||
 		ehdr.e_version != EV_CURRENT ||
diff --git a/include/linux/crash_dump.h b/include/linux/crash_dump.h
index 0026f26..088cd4a 100644
--- a/include/linux/crash_dump.h
+++ b/include/linux/crash_dump.h
@@ -20,7 +20,14 @@
 #define vmcore_elf_check_arch_cross(x) 0
 #endif
 
-#define vmcore_elf_check_arch(x) (elf_check_arch(x) || vmcore_elf_check_arch_cross(x))
+/*
+ * Architecture code can redefine this if there are any special checks
+ * needed for 64-bit ELF vmcores. In case of 32-bit only architecture,
+ * this can be set to zero.
+ */
+#ifndef vmcore_elf64_check_arch
+#define vmcore_elf64_check_arch(x) (elf_check_arch(x) || vmcore_elf_check_arch_cross(x))
+#endif
 
 /*
  * is_kdump_kernel() checks whether this kernel is booting after a panic of
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
index f2f32ee..038b3d1 100644
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -38,6 +38,7 @@
 static char gpfx;	/* prefix for global symbol name (sometimes '_') */
 static struct stat sb;	/* Remember .st_size, etc. */
 static jmp_buf jmpenv;	/* setjmp/longjmp per-file error escape */
+static const char *altmcount;	/* alternate mcount symbol name */
 
 /* setjmp() return values */
 enum {
@@ -299,7 +300,9 @@
 		fail_file();
 	} break;
 	case EM_386:	 reltype = R_386_32;                   break;
-	case EM_ARM:	 reltype = R_ARM_ABS32;                break;
+	case EM_ARM:	 reltype = R_ARM_ABS32;
+			 altmcount = "__gnu_mcount_nc";
+			 break;
 	case EM_IA_64:	 reltype = R_IA64_IMM64;   gpfx = '_'; break;
 	case EM_MIPS:	 /* reltype: e_class    */ gpfx = '_'; break;
 	case EM_PPC:	 reltype = R_PPC_ADDR32;   gpfx = '_'; break;
@@ -357,7 +360,7 @@
 int
 main(int argc, char const *argv[])
 {
-	const char ftrace[] = "kernel/trace/ftrace.o";
+	const char ftrace[] = "/ftrace.o";
 	int ftrace_size = sizeof(ftrace) - 1;
 	int n_error = 0;  /* gcc-4.3.0 false positive complaint */
 
diff --git a/scripts/recordmcount.h b/scripts/recordmcount.h
index 3966717..baf187b 100644
--- a/scripts/recordmcount.h
+++ b/scripts/recordmcount.h
@@ -275,11 +275,12 @@
 			Elf_Sym const *const symp =
 				&sym0[Elf_r_sym(relp)];
 			char const *symname = &str0[w(symp->st_name)];
+			char const *mcount = '_' == gpfx ? "_mcount" : "mcount";
 
 			if ('.' == symname[0])
 				++symname;  /* ppc64 hack */
-			if (0 == strcmp((('_' == gpfx) ? "_mcount" : "mcount"),
-					symname))
+			if (0 == strcmp(mcount, symname) ||
+			    (altmcount && 0 == strcmp(altmcount, symname)))
 				mcountsym = Elf_r_sym(relp);
 		}