Merge branches 'at91', 'davinci', 'imx', 'iop', 'ixp', 'ks8695', 'misc', 'pxa' and 's3c' into devel
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 68f2006..a0fa1ce 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -241,6 +241,9 @@
 
 config ARCH_IMX
 	bool "IMX"
+	select GENERIC_GPIO
+	select GENERIC_TIME
+	select GENERIC_CLOCKEVENTS
 	help
 	  Support for Motorola's i.MX family of processors (MX1, MXL).
 
@@ -385,6 +388,7 @@
 	bool "TI DaVinci"
 	select GENERIC_TIME
 	select GENERIC_CLOCKEVENTS
+	select GENERIC_GPIO
 	help
 	  Support for TI's DaVinci platform.
 
diff --git a/arch/arm/boot/compressed/.gitignore b/arch/arm/boot/compressed/.gitignore
index aefee20..b15f927 100644
--- a/arch/arm/boot/compressed/.gitignore
+++ b/arch/arm/boot/compressed/.gitignore
@@ -1 +1,2 @@
 piggy.gz
+font.c
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index adddc71..a1f1691 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -6,15 +6,13 @@
 
 HEAD	= head.o
 OBJS	= misc.o
-FONTC	= drivers/video/console/font_acorn_8x8.c
-
-FONT = $(addprefix ../../../../drivers/video/console/, font_acorn_8x8.o)
+FONTC	= $(srctree)/drivers/video/console/font_acorn_8x8.c
 
 #
 # Architecture dependencies
 #
 ifeq ($(CONFIG_ARCH_ACORN),y)
-OBJS		+= ll_char_wr.o $(FONT)
+OBJS		+= ll_char_wr.o font.o
 endif
 
 ifeq ($(CONFIG_ARCH_SHARK),y)
@@ -73,7 +71,7 @@
 
 SEDFLAGS	= s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/
 
-targets       := vmlinux vmlinux.lds piggy.gz piggy.o $(FONT) \
+targets       := vmlinux vmlinux.lds piggy.gz piggy.o font.o font.c \
 		 head.o misc.o $(OBJS)
 EXTRA_CFLAGS  := -fpic
 EXTRA_AFLAGS  :=
@@ -105,7 +103,10 @@
 
 $(obj)/piggy.o:  $(obj)/piggy.gz FORCE
 
-CFLAGS_font_acorn_8x8.o := -Dstatic=
+CFLAGS_font.o := -Dstatic=
+
+$(obj)/font.c: $(FONTC)
+	$(call cmd,shipped)
 
 $(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in arch/arm/boot/Makefile .config
 	@sed "$(SEDFLAGS)" < $< > $@
diff --git a/arch/arm/boot/compressed/head-xscale.S b/arch/arm/boot/compressed/head-xscale.S
index 73c5d9e..236bbe5 100644
--- a/arch/arm/boot/compressed/head-xscale.S
+++ b/arch/arm/boot/compressed/head-xscale.S
@@ -41,11 +41,6 @@
 		mov	r7, #MACH_TYPE_COTULLA_IDP
 #endif
 
-#ifdef  CONFIG_MACH_GTWX5715
-               mov     r7, #(MACH_TYPE_GTWX5715 & 0xff)
-               orr     r7, r7, #(MACH_TYPE_GTWX5715 & 0xff00)
-#endif
-
 #ifdef CONFIG_ARCH_IXP2000
 		mov	r1, #-1
 		mov	r0, #0xd6000000
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 680ea6e..d7fb5ee1 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -436,6 +436,28 @@
 		mcr	p15, 0, r0, c8, c7, 0	@ flush I,D TLBs
 		mov	pc, r12
 
+__armv7_mmu_cache_on:
+		mov	r12, lr
+		mrc	p15, 0, r11, c0, c1, 4	@ read ID_MMFR0
+		tst	r11, #0xf		@ VMSA
+		blne	__setup_mmu
+		mov	r0, #0
+		mcr	p15, 0, r0, c7, c10, 4	@ drain write buffer
+		tst	r11, #0xf		@ VMSA
+		mcrne	p15, 0, r0, c8, c7, 0	@ flush I,D TLBs
+		mrc	p15, 0, r0, c1, c0, 0	@ read control reg
+		orr	r0, r0, #0x5000		@ I-cache enable, RR cache replacement
+		orr	r0, r0, #0x003c		@ write buffer
+		orrne	r0, r0, #1		@ MMU enabled
+		movne	r1, #-1
+		mcrne	p15, 0, r3, c2, c0, 0	@ load page table pointer
+		mcrne	p15, 0, r1, c3, c0, 0	@ load domain access control
+		mcr	p15, 0, r0, c1, c0, 0	@ load control register
+		mrc	p15, 0, r0, c1, c0, 0	@ and read it back
+		mov	r0, #0
+		mcr	p15, 0, r0, c7, c5, 4	@ ISB
+		mov	pc, r12
+
 __arm6_mmu_cache_on:
 		mov	r12, lr
 		bl	__setup_mmu
@@ -622,11 +644,17 @@
 		b	__armv4_mmu_cache_flush
 
 		.word	0x0007b000		@ ARMv6
-		.word	0x0007f000
+		.word	0x000ff000
 		b	__armv4_mmu_cache_on
 		b	__armv4_mmu_cache_off
 		b	__armv6_mmu_cache_flush
 
+		.word	0x000f0000		@ new CPU Id
+		.word	0x000f0000
+		b	__armv7_mmu_cache_on
+		b	__armv7_mmu_cache_off
+		b	__armv7_mmu_cache_flush
+
 		.word	0			@ unrecognised type
 		.word	0
 		mov	pc, lr
@@ -674,6 +702,16 @@
 		mcr	p15, 0, r0, c8, c7	@ invalidate whole TLB v4
 		mov	pc, lr
 
+__armv7_mmu_cache_off:
+		mrc	p15, 0, r0, c1, c0
+		bic	r0, r0, #0x000d
+		mcr	p15, 0, r0, c1, c0	@ turn MMU and cache off
+		mov	r12, lr
+		bl	__armv7_mmu_cache_flush
+		mov	r0, #0
+		mcr	p15, 0, r0, c8, c7, 0	@ invalidate whole TLB
+		mov	pc, r12
+
 __arm6_mmu_cache_off:
 		mov	r0, #0x00000030		@ ARM6 control reg.
 		b	__armv3_mmu_cache_off
@@ -730,6 +768,59 @@
 		mcr	p15, 0, r1, c7, c10, 4	@ drain WB
 		mov	pc, lr
 
+__armv7_mmu_cache_flush:
+		mrc	p15, 0, r10, c0, c1, 5	@ read ID_MMFR1
+		tst	r10, #0xf << 16		@ hierarchical cache (ARMv7)
+		beq	hierarchical
+		mov	r10, #0
+		mcr	p15, 0, r10, c7, c14, 0	@ clean+invalidate D
+		b	iflush
+hierarchical:
+		stmfd	sp!, {r0-r5, r7, r9-r11}
+		mrc	p15, 1, r0, c0, c0, 1	@ read clidr
+		ands	r3, r0, #0x7000000	@ extract loc from clidr
+		mov	r3, r3, lsr #23		@ left align loc bit field
+		beq	finished		@ if loc is 0, then no need to clean
+		mov	r10, #0			@ start clean at cache level 0
+loop1:
+		add	r2, r10, r10, lsr #1	@ work out 3x current cache level
+		mov	r1, r0, lsr r2		@ extract cache type bits from clidr
+		and	r1, r1, #7		@ mask of the bits for current cache only
+		cmp	r1, #2			@ see what cache we have at this level
+		blt	skip			@ skip if no cache, or just i-cache
+		mcr	p15, 2, r10, c0, c0, 0	@ select current cache level in cssr
+		mcr	p15, 0, r10, c7, c5, 4	@ isb to sych the new cssr&csidr
+		mrc	p15, 1, r1, c0, c0, 0	@ read the new csidr
+		and	r2, r1, #7		@ extract the length of the cache lines
+		add	r2, r2, #4		@ add 4 (line length offset)
+		ldr	r4, =0x3ff
+		ands	r4, r4, r1, lsr #3	@ find maximum number on the way size
+		.word	0xe16f5f14		@ clz r5, r4 - find bit position of way size increment
+		ldr	r7, =0x7fff
+		ands	r7, r7, r1, lsr #13	@ extract max number of the index size
+loop2:
+		mov	r9, r4			@ create working copy of max way size
+loop3:
+		orr	r11, r10, r9, lsl r5	@ factor way and cache number into r11
+		orr	r11, r11, r7, lsl r2	@ factor index number into r11
+		mcr	p15, 0, r11, c7, c14, 2	@ clean & invalidate by set/way
+		subs	r9, r9, #1		@ decrement the way
+		bge	loop3
+		subs	r7, r7, #1		@ decrement the index
+		bge	loop2
+skip:
+		add	r10, r10, #2		@ increment cache number
+		cmp	r3, r10
+		bgt	loop1
+finished:
+		mov	r10, #0			@ swith back to cache level 0
+		mcr	p15, 2, r10, c0, c0, 0	@ select current cache level in cssr
+		ldmfd	sp!, {r0-r5, r7, r9-r11}
+iflush:
+		mcr	p15, 0, r10, c7, c5, 0	@ invalidate I+BTB
+		mcr	p15, 0, r10, c7, c10, 4	@ drain WB
+		mov	pc, lr
+
 __armv4_mmu_cache_flush:
 		mov	r2, #64*1024		@ default: 32K dcache size (*2)
 		mov	r11, #32		@ default: 32 byte line size
diff --git a/arch/arm/common/sharpsl_pm.c b/arch/arm/common/sharpsl_pm.c
index 3bf3a92..111a7fa5 100644
--- a/arch/arm/common/sharpsl_pm.c
+++ b/arch/arm/common/sharpsl_pm.c
@@ -766,9 +766,7 @@
 }
 
 static struct pm_ops sharpsl_pm_ops = {
-	.prepare	= pxa_pm_prepare,
 	.enter		= corgi_pxa_pm_enter,
-	.finish		= pxa_pm_finish,
 	.valid		= pm_valid_only_mem,
 };
 
diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S
index a52da0d..024a9cf 100644
--- a/arch/arm/kernel/head-common.S
+++ b/arch/arm/kernel/head-common.S
@@ -20,7 +20,8 @@
 	.long	_end				@ r7
 	.long	processor_id			@ r4
 	.long	__machine_arch_type		@ r5
-	.long	cr_alignment			@ r6
+	.long	__atags_pointer			@ r6
+	.long	cr_alignment			@ r7
 	.long	init_thread_union + THREAD_START_SP @ sp
 
 /*
@@ -29,6 +30,7 @@
  *
  *  r0  = cp#15 control register
  *  r1  = machine ID
+ *  r2  = atags pointer
  *  r9  = processor ID
  */
 	.type	__mmap_switched, %function
@@ -47,11 +49,12 @@
 	strcc	fp, [r6],#4
 	bcc	1b
 
-	ldmia	r3, {r4, r5, r6, sp}
+	ldmia	r3, {r4, r5, r6, r7, sp}
 	str	r9, [r4]			@ Save processor ID
 	str	r1, [r5]			@ Save machine type
+	str	r2, [r6]			@ Save atags pointer
 	bic	r4, r0, #CR_A			@ Clear 'A' bit
-	stmia	r6, {r0, r4}			@ Save control register values
+	stmia	r7, {r0, r4}			@ Save control register values
 	b	start_kernel
 
 /*
@@ -215,3 +218,34 @@
 	bl	__lookup_machine_type
 	mov	r0, r5
 	ldmfd	sp!, {r4 - r6, pc}
+
+/* Determine validity of the r2 atags pointer.  The heuristic requires
+ * that the pointer be aligned, in the first 16k of physical RAM and
+ * that the ATAG_CORE marker is first and present.  Future revisions
+ * of this function may be more lenient with the physical address and
+ * may also be able to move the ATAGS block if necessary.
+ *
+ * r8  = machinfo
+ *
+ * Returns:
+ *  r2 either valid atags pointer, or zero
+ *  r5, r6 corrupted
+ */
+
+	.type	__vet_atags, %function
+__vet_atags:
+	tst	r2, #0x3			@ aligned?
+	bne	1f
+
+	ldr	r5, [r2, #0]			@ is first tag ATAG_CORE?
+	subs	r5, r5, #ATAG_CORE_SIZE
+	bne	1f
+	ldr	r5, [r2, #4]
+	ldr	r6, =ATAG_CORE
+	cmp	r5, r6
+	bne	1f
+
+	mov	pc, lr				@ atag pointer is ok
+
+1:	mov	r2, #0
+	mov	pc, lr
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 41f98b4..7898cbc 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -29,6 +29,10 @@
 #define KERNEL_RAM_VADDR	(PAGE_OFFSET + TEXT_OFFSET)
 #define KERNEL_RAM_PADDR	(PHYS_OFFSET + TEXT_OFFSET)
 
+#define ATAG_CORE 0x54410001
+#define ATAG_CORE_SIZE ((2*4 + 3*4) >> 2)
+
+
 /*
  * swapper_pg_dir is the virtual address of the initial page table.
  * We place the page tables 16K below KERNEL_RAM_VADDR.  Therefore, we must
@@ -61,7 +65,7 @@
  *
  * This is normally called from the decompressor code.  The requirements
  * are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0,
- * r1 = machine nr.
+ * r1 = machine nr, r2 = atags pointer.
  *
  * This code is mostly position independent, so if you link the kernel at
  * 0xc0008000, you call this at __pa(0xc0008000).
@@ -85,6 +89,7 @@
 	bl	__lookup_machine_type		@ r5=machinfo
 	movs	r8, r5				@ invalid machine (r5=0)?
 	beq	__error_a			@ yes, error 'a'
+	bl	__vet_atags
 	bl	__create_page_tables
 
 	/*
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 8423617..93b7f8e 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -44,6 +44,10 @@
   "UK8_32" , "UK9_32" , "UK10_32", "UND_32" , "UK12_32", "UK13_32", "UK14_32", "SYS_32"
 };
 
+static const char *isa_modes[] = {
+  "ARM" , "Thumb" , "Jazelle", "ThumbEE"
+};
+
 extern void setup_mm_for_reboot(char mode);
 
 static volatile int hlt_counter;
@@ -230,11 +234,11 @@
 	buf[3] = flags & PSR_V_BIT ? 'V' : 'v';
 	buf[4] = '\0';
 
-	printk("Flags: %s  IRQs o%s  FIQs o%s  Mode %s%s  Segment %s\n",
+	printk("Flags: %s  IRQs o%s  FIQs o%s  Mode %s  ISA %s  Segment %s\n",
 		buf, interrupts_enabled(regs) ? "n" : "ff",
 		fast_interrupts_enabled(regs) ? "n" : "ff",
 		processor_modes[processor_mode(regs)],
-		thumb_mode(regs) ? " (T)" : "",
+		isa_modes[isa_mode(regs)],
 		get_fs() == get_ds() ? "kernel" : "user");
 #ifdef CONFIG_CPU_CP15
 	{
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 650eac1..5be2e98 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -63,6 +63,8 @@
 unsigned int __machine_arch_type;
 EXPORT_SYMBOL(__machine_arch_type);
 
+unsigned int __atags_pointer __initdata;
+
 unsigned int system_rev;
 EXPORT_SYMBOL(system_rev);
 
@@ -780,7 +782,9 @@
 	if (mdesc->soft_reboot)
 		reboot_setup("s");
 
-	if (mdesc->boot_params)
+	if (__atags_pointer)
+		tags = phys_to_virt(__atags_pointer);
+	else if (mdesc->boot_params)
 		tags = phys_to_virt(mdesc->boot_params);
 
 	/*
diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c
index 26ca8ab3..42e172c 100644
--- a/arch/arm/mach-at91/board-sam9261ek.c
+++ b/arch/arm/mach-at91/board-sam9261ek.c
@@ -27,6 +27,11 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
 #include <linux/dm9000.h>
+#include <linux/fb.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+
+#include <video/atmel_lcdc.h>
 
 #include <asm/hardware.h>
 #include <asm/setup.h>
@@ -271,6 +276,127 @@
 };
 
 
+/*
+ * LCD Controller
+ */
+#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE)
+static struct fb_videomode at91_tft_vga_modes[] = {
+	{
+	        .name           = "TX09D50VM1CCA @ 60",
+		.refresh	= 60,
+		.xres		= 240,		.yres		= 320,
+		.pixclock	= KHZ2PICOS(4965),
+
+		.left_margin	= 1,		.right_margin	= 33,
+		.upper_margin	= 1,		.lower_margin	= 0,
+		.hsync_len	= 5,		.vsync_len	= 1,
+
+		.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+};
+
+static struct fb_monspecs at91fb_default_monspecs = {
+	.manufacturer	= "HIT",
+	.monitor        = "TX09D50VM1CCA",
+
+	.modedb		= at91_tft_vga_modes,
+	.modedb_len	= ARRAY_SIZE(at91_tft_vga_modes),
+	.hfmin		= 15000,
+	.hfmax		= 64000,
+	.vfmin		= 50,
+	.vfmax		= 150,
+};
+
+#define AT91SAM9261_DEFAULT_LCDCON2 	(ATMEL_LCDC_MEMOR_LITTLE \
+					| ATMEL_LCDC_DISTYPE_TFT    \
+					| ATMEL_LCDC_CLKMOD_ALWAYSACTIVE)
+
+static void at91_lcdc_power_control(int on)
+{
+	if (on)
+		at91_set_gpio_value(AT91_PIN_PA12, 0);	/* power up */
+	else
+		at91_set_gpio_value(AT91_PIN_PA12, 1);	/* power down */
+}
+
+/* Driver datas */
+static struct atmel_lcdfb_info __initdata ek_lcdc_data = {
+	.default_bpp			= 16,
+	.default_dmacon			= ATMEL_LCDC_DMAEN,
+	.default_lcdcon2		= AT91SAM9261_DEFAULT_LCDCON2,
+	.default_monspecs		= &at91fb_default_monspecs,
+	.atmel_lcdfb_power_control	= at91_lcdc_power_control,
+	.guard_time			= 1,
+};
+
+#else
+static struct atmel_lcdfb_info __initdata ek_lcdc_data;
+#endif
+
+
+/*
+ * GPIO Buttons
+ */
+#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
+static struct gpio_keys_button ek_buttons[] = {
+	{
+		.gpio		= AT91_PIN_PA27,
+		.keycode	= BTN_0,
+		.desc		= "Button 0",
+		.active_low	= 1,
+	},
+	{
+		.gpio		= AT91_PIN_PA26,
+		.keycode	= BTN_1,
+		.desc		= "Button 1",
+		.active_low	= 1,
+	},
+	{
+		.gpio		= AT91_PIN_PA25,
+		.keycode	= BTN_2,
+		.desc		= "Button 2",
+		.active_low	= 1,
+	},
+	{
+		.gpio		= AT91_PIN_PA24,
+		.keycode	= BTN_3,
+		.desc		= "Button 3",
+		.active_low	= 1,
+	}
+};
+
+static struct gpio_keys_platform_data ek_button_data = {
+	.buttons	= ek_buttons,
+	.nbuttons	= ARRAY_SIZE(ek_buttons),
+};
+
+static struct platform_device ek_button_device = {
+	.name		= "gpio-keys",
+	.id		= -1,
+	.num_resources	= 0,
+	.dev		= {
+		.platform_data	= &ek_button_data,
+	}
+};
+
+static void __init ek_add_device_buttons(void)
+{
+	at91_set_gpio_input(AT91_PIN_PB27, 0);	/* btn0 */
+	at91_set_deglitch(AT91_PIN_PB27, 1);
+	at91_set_gpio_input(AT91_PIN_PB26, 0);	/* btn1 */
+	at91_set_deglitch(AT91_PIN_PB26, 1);
+	at91_set_gpio_input(AT91_PIN_PB25, 0);	/* btn2 */
+	at91_set_deglitch(AT91_PIN_PB25, 1);
+	at91_set_gpio_input(AT91_PIN_PB24, 0);	/* btn3 */
+	at91_set_deglitch(AT91_PIN_PB24, 1);
+
+	platform_device_register(&ek_button_device);
+}
+#else
+static void __init ek_add_device_buttons(void) {}
+#endif
+
 static void __init ek_board_init(void)
 {
 	/* Serial */
@@ -296,6 +422,10 @@
 	/* MMC */
 	at91_add_device_mmc(0, &ek_mmc_data);
 #endif
+	/* LCD Controller */
+	at91_add_device_lcdc(&ek_lcdc_data);
+	/* Push Buttons */
+	ek_add_device_buttons();
 }
 
 MACHINE_START(AT91SAM9261EK, "Atmel AT91SAM9261-EK")
diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
index c164c8e..2a1cc73 100644
--- a/arch/arm/mach-at91/board-sam9263ek.c
+++ b/arch/arm/mach-at91/board-sam9263ek.c
@@ -26,6 +26,9 @@
 #include <linux/platform_device.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
+#include <linux/fb.h>
+
+#include <video/atmel_lcdc.h>
 
 #include <asm/hardware.h>
 #include <asm/setup.h>
@@ -202,6 +205,65 @@
 
 
 /*
+ * LCD Controller
+ */
+#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE)
+static struct fb_videomode at91_tft_vga_modes[] = {
+	{
+	        .name           = "TX09D50VM1CCA @ 60",
+		.refresh	= 60,
+		.xres		= 240,		.yres		= 320,
+		.pixclock	= KHZ2PICOS(4965),
+
+		.left_margin	= 1,		.right_margin	= 33,
+		.upper_margin	= 1,		.lower_margin	= 0,
+		.hsync_len	= 5,		.vsync_len	= 1,
+
+		.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+};
+
+static struct fb_monspecs at91fb_default_monspecs = {
+	.manufacturer	= "HIT",
+	.monitor        = "TX09D70VM1CCA",
+
+	.modedb		= at91_tft_vga_modes,
+	.modedb_len	= ARRAY_SIZE(at91_tft_vga_modes),
+	.hfmin		= 15000,
+	.hfmax		= 64000,
+	.vfmin		= 50,
+	.vfmax		= 150,
+};
+
+#define AT91SAM9263_DEFAULT_LCDCON2 	(ATMEL_LCDC_MEMOR_LITTLE \
+					| ATMEL_LCDC_DISTYPE_TFT    \
+					| ATMEL_LCDC_CLKMOD_ALWAYSACTIVE)
+
+static void at91_lcdc_power_control(int on)
+{
+	if (on)
+		at91_set_gpio_value(AT91_PIN_PD12, 0);	/* power up */
+	else
+		at91_set_gpio_value(AT91_PIN_PD12, 1);	/* power down */
+}
+
+/* Driver datas */
+static struct atmel_lcdfb_info __initdata ek_lcdc_data = {
+	.default_bpp			= 16,
+	.default_dmacon			= ATMEL_LCDC_DMAEN,
+	.default_lcdcon2		= AT91SAM9263_DEFAULT_LCDCON2,
+	.default_monspecs		= &at91fb_default_monspecs,
+	.atmel_lcdfb_power_control	= at91_lcdc_power_control,
+	.guard_time			= 1,
+};
+
+#else
+static struct atmel_lcdfb_info __initdata ek_lcdc_data;
+#endif
+
+
+/*
  * AC97
  */
 static struct atmel_ac97_data ek_ac97_data = {
@@ -230,6 +292,8 @@
 	at91_add_device_nand(&ek_nand_data);
 	/* I2C */
 	at91_add_device_i2c();
+	/* LCD Controller */
+	at91_add_device_lcdc(&ek_lcdc_data);
 	/* AC97 */
 	at91_add_device_ac97(&ek_ac97_data);
 }
diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile
index a8f88cd..99ac2e5 100644
--- a/arch/arm/mach-davinci/Makefile
+++ b/arch/arm/mach-davinci/Makefile
@@ -4,7 +4,8 @@
 #
 
 # Common objects
-obj-y 			:= time.o irq.o serial.o io.o id.o psc.o
+obj-y 			:= time.o irq.o clock.o serial.o io.o id.o psc.o \
+			   gpio.o mux.o
 
 # Board specific
 obj-$(CONFIG_MACH_DAVINCI_EVM)  += board-evm.o
diff --git a/arch/arm/mach-davinci/board-evm.c b/arch/arm/mach-davinci/board-evm.c
index 633c12e..9e4024c 100644
--- a/arch/arm/mach-davinci/board-evm.c
+++ b/arch/arm/mach-davinci/board-evm.c
@@ -32,6 +32,7 @@
 void __init davinci_psc_init(void);
 void __init davinci_irq_init(void);
 void __init davinci_map_common_io(void);
+void __init davinci_init_common_hw(void);
 
 /* NOR Flash base address set to CS0 by default */
 #define NOR_FLASH_PHYS 0x02000000
@@ -116,6 +117,7 @@
 
 static __init void davinci_evm_irq_init(void)
 {
+	davinci_init_common_hw();
 	davinci_irq_init();
 }
 
diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c
new file mode 100644
index 0000000..139ceaa
--- /dev/null
+++ b/arch/arm/mach-davinci/clock.c
@@ -0,0 +1,323 @@
+/*
+ * TI DaVinci clock config file
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+#include <asm/arch/psc.h>
+#include "clock.h"
+
+/* PLL/Reset register offsets */
+#define PLLM		0x110
+
+static LIST_HEAD(clocks);
+static DEFINE_MUTEX(clocks_mutex);
+static DEFINE_SPINLOCK(clockfw_lock);
+
+static unsigned int commonrate;
+static unsigned int armrate;
+static unsigned int fixedrate = 27000000;	/* 27 MHZ */
+
+extern void davinci_psc_config(unsigned int domain, unsigned int id, char enable);
+
+/*
+ * Returns a clock. Note that we first try to use device id on the bus
+ * and clock name. If this fails, we try to use clock name only.
+ */
+struct clk *clk_get(struct device *dev, const char *id)
+{
+	struct clk *p, *clk = ERR_PTR(-ENOENT);
+	int idno;
+
+	if (dev == NULL || dev->bus != &platform_bus_type)
+		idno = -1;
+	else
+		idno = to_platform_device(dev)->id;
+
+	mutex_lock(&clocks_mutex);
+
+	list_for_each_entry(p, &clocks, node) {
+		if (p->id == idno &&
+		    strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
+			clk = p;
+			goto found;
+		}
+	}
+
+	list_for_each_entry(p, &clocks, node) {
+		if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
+			clk = p;
+			break;
+		}
+	}
+
+found:
+	mutex_unlock(&clocks_mutex);
+
+	return clk;
+}
+EXPORT_SYMBOL(clk_get);
+
+void clk_put(struct clk *clk)
+{
+	if (clk && !IS_ERR(clk))
+		module_put(clk->owner);
+}
+EXPORT_SYMBOL(clk_put);
+
+static int __clk_enable(struct clk *clk)
+{
+	if (clk->flags & ALWAYS_ENABLED)
+		return 0;
+
+	davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, clk->lpsc, 1);
+	return 0;
+}
+
+static void __clk_disable(struct clk *clk)
+{
+	if (clk->usecount)
+		return;
+
+	davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, clk->lpsc, 0);
+}
+
+int clk_enable(struct clk *clk)
+{
+	unsigned long flags;
+	int ret = 0;
+
+	if (clk == NULL || IS_ERR(clk))
+		return -EINVAL;
+
+	if (clk->usecount++ == 0) {
+		spin_lock_irqsave(&clockfw_lock, flags);
+		ret = __clk_enable(clk);
+		spin_unlock_irqrestore(&clockfw_lock, flags);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+	unsigned long flags;
+
+	if (clk == NULL || IS_ERR(clk))
+		return;
+
+	if (clk->usecount > 0 && !(--clk->usecount)) {
+		spin_lock_irqsave(&clockfw_lock, flags);
+		__clk_disable(clk);
+		spin_unlock_irqrestore(&clockfw_lock, flags);
+	}
+}
+EXPORT_SYMBOL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	if (clk == NULL || IS_ERR(clk))
+		return -EINVAL;
+
+	return *(clk->rate);
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	if (clk == NULL || IS_ERR(clk))
+		return -EINVAL;
+
+	return *(clk->rate);
+}
+EXPORT_SYMBOL(clk_round_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	if (clk == NULL || IS_ERR(clk))
+		return -EINVAL;
+
+	/* changing the clk rate is not supported */
+	return -EINVAL;
+}
+EXPORT_SYMBOL(clk_set_rate);
+
+int clk_register(struct clk *clk)
+{
+	if (clk == NULL || IS_ERR(clk))
+		return -EINVAL;
+
+	mutex_lock(&clocks_mutex);
+	list_add(&clk->node, &clocks);
+	mutex_unlock(&clocks_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL(clk_register);
+
+void clk_unregister(struct clk *clk)
+{
+	if (clk == NULL || IS_ERR(clk))
+		return;
+
+	mutex_lock(&clocks_mutex);
+	list_del(&clk->node);
+	mutex_unlock(&clocks_mutex);
+}
+EXPORT_SYMBOL(clk_unregister);
+
+static struct clk davinci_clks[] = {
+	{
+		.name = "ARMCLK",
+		.rate = &armrate,
+		.lpsc = -1,
+		.flags = ALWAYS_ENABLED,
+	},
+	{
+		.name = "UART",
+		.rate = &fixedrate,
+		.lpsc = DAVINCI_LPSC_UART0,
+	},
+	{
+		.name = "EMACCLK",
+		.rate = &commonrate,
+		.lpsc = DAVINCI_LPSC_EMAC_WRAPPER,
+	},
+	{
+		.name = "I2CCLK",
+		.rate = &fixedrate,
+		.lpsc = DAVINCI_LPSC_I2C,
+	},
+	{
+		.name = "IDECLK",
+		.rate = &commonrate,
+		.lpsc = DAVINCI_LPSC_ATA,
+	},
+	{
+		.name = "McBSPCLK",
+		.rate = &commonrate,
+		.lpsc = DAVINCI_LPSC_McBSP,
+	},
+	{
+		.name = "MMCSDCLK",
+		.rate = &commonrate,
+		.lpsc = DAVINCI_LPSC_MMC_SD,
+	},
+	{
+		.name = "SPICLK",
+		.rate = &commonrate,
+		.lpsc = DAVINCI_LPSC_SPI,
+	},
+	{
+		.name = "gpio",
+		.rate = &commonrate,
+		.lpsc = DAVINCI_LPSC_GPIO,
+	},
+	{
+		.name = "AEMIFCLK",
+		.rate = &commonrate,
+		.lpsc = DAVINCI_LPSC_AEMIF,
+		.usecount = 1,
+	}
+};
+
+int __init davinci_clk_init(void)
+{
+	struct clk *clkp;
+	int count = 0;
+	u32 pll_mult;
+
+	pll_mult = davinci_readl(DAVINCI_PLL_CNTRL0_BASE + PLLM);
+	commonrate = ((pll_mult + 1) * 27000000) / 6;
+	armrate = ((pll_mult + 1) * 27000000) / 2;
+
+	for (clkp = davinci_clks; count < ARRAY_SIZE(davinci_clks);
+	     count++, clkp++) {
+		clk_register(clkp);
+
+		/* Turn on clocks that have been enabled in the
+		 * table above */
+		if (clkp->usecount)
+			clk_enable(clkp);
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_PROC_FS
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
+static void *davinci_ck_start(struct seq_file *m, loff_t *pos)
+{
+	return *pos < 1 ? (void *)1 : NULL;
+}
+
+static void *davinci_ck_next(struct seq_file *m, void *v, loff_t *pos)
+{
+	++*pos;
+	return NULL;
+}
+
+static void davinci_ck_stop(struct seq_file *m, void *v)
+{
+}
+
+static int davinci_ck_show(struct seq_file *m, void *v)
+{
+	struct clk *cp;
+
+	list_for_each_entry(cp, &clocks, node)
+		seq_printf(m,"%s %d %d\n", cp->name, *(cp->rate), cp->usecount);
+
+	return 0;
+}
+
+static struct seq_operations davinci_ck_op = {
+	.start	= davinci_ck_start,
+	.next	= davinci_ck_next,
+	.stop	= davinci_ck_stop,
+	.show	= davinci_ck_show
+};
+
+static int davinci_ck_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &davinci_ck_op);
+}
+
+static struct file_operations proc_davinci_ck_operations = {
+	.open		= davinci_ck_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
+static int __init davinci_ck_proc_init(void)
+{
+	struct proc_dir_entry *entry;
+
+	entry = create_proc_entry("davinci_clocks", 0, NULL);
+	if (entry)
+		entry->proc_fops = &proc_davinci_ck_operations;
+	return 0;
+
+}
+__initcall(davinci_ck_proc_init);
+#endif	/* CONFIG_DEBUG_PROC_FS */
diff --git a/arch/arm/mach-davinci/clock.h b/arch/arm/mach-davinci/clock.h
new file mode 100644
index 0000000..ed47079
--- /dev/null
+++ b/arch/arm/mach-davinci/clock.h
@@ -0,0 +1,33 @@
+/*
+ * TI DaVinci clock definitions
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ *
+ * 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 __ARCH_ARM_DAVINCI_CLOCK_H
+#define __ARCH_ARM_DAVINCI_CLOCK_H
+
+struct clk {
+	struct list_head	node;
+	struct module		*owner;
+	const char		*name;
+	unsigned int		*rate;
+	int			id;
+	__s8			usecount;
+	__u8			flags;
+	__u8			lpsc;
+};
+
+/* Clock flags */
+#define RATE_CKCTL		1
+#define RATE_FIXED		2
+#define RATE_PROPAGATES		4
+#define VIRTUAL_CLOCK		8
+#define ALWAYS_ENABLED		16
+#define ENABLE_REG_32BIT	32
+
+#endif
diff --git a/arch/arm/mach-davinci/gpio.c b/arch/arm/mach-davinci/gpio.c
new file mode 100644
index 0000000..9c67886
--- /dev/null
+++ b/arch/arm/mach-davinci/gpio.c
@@ -0,0 +1,286 @@
+/*
+ * TI DaVinci GPIO Support
+ *
+ * Copyright (c) 2006 David Brownell
+ * Copyright (c) 2007, MontaVista Software, Inc. <source@mvista.com>
+ *
+ * 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.
+ */
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/bitops.h>
+
+#include <asm/arch/irqs.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/gpio.h>
+
+#include <asm/mach/irq.h>
+
+static DEFINE_SPINLOCK(gpio_lock);
+static DECLARE_BITMAP(gpio_in_use, DAVINCI_N_GPIO);
+
+int gpio_request(unsigned gpio, const char *tag)
+{
+	if (gpio >= DAVINCI_N_GPIO)
+		return -EINVAL;
+
+	if (test_and_set_bit(gpio, gpio_in_use))
+		return -EBUSY;
+
+	return 0;
+}
+EXPORT_SYMBOL(gpio_request);
+
+void gpio_free(unsigned gpio)
+{
+	if (gpio >= DAVINCI_N_GPIO)
+		return;
+
+	clear_bit(gpio, gpio_in_use);
+}
+EXPORT_SYMBOL(gpio_free);
+
+/* create a non-inlined version */
+static struct gpio_controller *__iomem gpio2controller(unsigned gpio)
+{
+	return __gpio_to_controller(gpio);
+}
+
+/*
+ * Assuming the pin is muxed as a gpio output, set its output value.
+ */
+void __gpio_set(unsigned gpio, int value)
+{
+	struct gpio_controller *__iomem g = gpio2controller(gpio);
+
+	__raw_writel(__gpio_mask(gpio), value ? &g->set_data : &g->clr_data);
+}
+EXPORT_SYMBOL(__gpio_set);
+
+
+/*
+ * Read the pin's value (works even if it's set up as output);
+ * returns zero/nonzero.
+ *
+ * Note that changes are synched to the GPIO clock, so reading values back
+ * right after you've set them may give old values.
+ */
+int __gpio_get(unsigned gpio)
+{
+	struct gpio_controller *__iomem g = gpio2controller(gpio);
+
+	return !!(__gpio_mask(gpio) & __raw_readl(&g->in_data));
+}
+EXPORT_SYMBOL(__gpio_get);
+
+
+/*--------------------------------------------------------------------------*/
+
+/*
+ * board setup code *MUST* set PINMUX0 and PINMUX1 as
+ * needed, and enable the GPIO clock.
+ */
+
+int gpio_direction_input(unsigned gpio)
+{
+	struct gpio_controller *__iomem g = gpio2controller(gpio);
+	u32 temp;
+	u32 mask;
+
+	if (!g)
+		return -EINVAL;
+
+	spin_lock(&gpio_lock);
+	mask = __gpio_mask(gpio);
+	temp = __raw_readl(&g->dir);
+	temp |= mask;
+	__raw_writel(temp, &g->dir);
+	spin_unlock(&gpio_lock);
+	return 0;
+}
+EXPORT_SYMBOL(gpio_direction_input);
+
+int gpio_direction_output(unsigned gpio, int value)
+{
+	struct gpio_controller *__iomem g = gpio2controller(gpio);
+	u32 temp;
+	u32 mask;
+
+	if (!g)
+		return -EINVAL;
+
+	spin_lock(&gpio_lock);
+	mask = __gpio_mask(gpio);
+	temp = __raw_readl(&g->dir);
+	temp &= ~mask;
+	__raw_writel(mask, value ? &g->set_data : &g->clr_data);
+	__raw_writel(temp, &g->dir);
+	spin_unlock(&gpio_lock);
+	return 0;
+}
+EXPORT_SYMBOL(gpio_direction_output);
+
+/*
+ * We expect irqs will normally be set up as input pins, but they can also be
+ * used as output pins ... which is convenient for testing.
+ *
+ * NOTE:  GPIO0..GPIO7 also have direct INTC hookups, which work in addition
+ * to their GPIOBNK0 irq (but with a bit less overhead).  But we don't have
+ * a good way to hook those up ...
+ *
+ * All those INTC hookups (GPIO0..GPIO7 plus five IRQ banks) can also
+ * serve as EDMA event triggers.
+ */
+
+static void gpio_irq_disable(unsigned irq)
+{
+	struct gpio_controller *__iomem g = get_irq_chip_data(irq);
+	u32 mask = __gpio_mask(irq_to_gpio(irq));
+
+	__raw_writel(mask, &g->clr_falling);
+	__raw_writel(mask, &g->clr_rising);
+}
+
+static void gpio_irq_enable(unsigned irq)
+{
+	struct gpio_controller *__iomem g = get_irq_chip_data(irq);
+	u32 mask = __gpio_mask(irq_to_gpio(irq));
+
+	if (irq_desc[irq].status & IRQ_TYPE_EDGE_FALLING)
+		__raw_writel(mask, &g->set_falling);
+	if (irq_desc[irq].status & IRQ_TYPE_EDGE_RISING)
+		__raw_writel(mask, &g->set_rising);
+}
+
+static int gpio_irq_type(unsigned irq, unsigned trigger)
+{
+	struct gpio_controller *__iomem g = get_irq_chip_data(irq);
+	u32 mask = __gpio_mask(irq_to_gpio(irq));
+
+	if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
+		return -EINVAL;
+
+	irq_desc[irq].status &= ~IRQ_TYPE_SENSE_MASK;
+	irq_desc[irq].status |= trigger;
+
+	__raw_writel(mask, (trigger & IRQ_TYPE_EDGE_FALLING)
+		     ? &g->set_falling : &g->clr_falling);
+	__raw_writel(mask, (trigger & IRQ_TYPE_EDGE_RISING)
+		     ? &g->set_rising : &g->clr_rising);
+	return 0;
+}
+
+static struct irq_chip gpio_irqchip = {
+	.name		= "GPIO",
+	.enable		= gpio_irq_enable,
+	.disable	= gpio_irq_disable,
+	.set_type	= gpio_irq_type,
+};
+
+static void
+gpio_irq_handler(unsigned irq, struct irq_desc *desc)
+{
+	struct gpio_controller *__iomem g = get_irq_chip_data(irq);
+	u32 mask = 0xffff;
+
+	/* we only care about one bank */
+	if (irq & 1)
+		mask <<= 16;
+
+	/* temporarily mask (level sensitive) parent IRQ */
+	desc->chip->ack(irq);
+	while (1) {
+		u32		status;
+		struct irq_desc	*gpio;
+		int		n;
+		int		res;
+
+		/* ack any irqs */
+		status = __raw_readl(&g->intstat) & mask;
+		if (!status)
+			break;
+		__raw_writel(status, &g->intstat);
+		if (irq & 1)
+			status >>= 16;
+
+		/* now demux them to the right lowlevel handler */
+		n = (int)get_irq_data(irq);
+		gpio = &irq_desc[n];
+		while (status) {
+			res = ffs(status);
+			n += res;
+			gpio += res;
+			desc_handle_irq(n - 1, gpio - 1);
+			status >>= res;
+		}
+	}
+	desc->chip->unmask(irq);
+	/* now it may re-trigger */
+}
+
+/*
+ * NOTE:  for suspend/resume, probably best to make a sysdev (and class)
+ * with its suspend/resume calls hooking into the results of the set_wake()
+ * calls ... so if no gpios are wakeup events the clock can be disabled,
+ * with outputs left at previously set levels, and so that VDD3P3V.IOPWDN0
+ * can be set appropriately for GPIOV33 pins.
+ */
+
+static int __init davinci_gpio_irq_setup(void)
+{
+	unsigned	gpio, irq, bank;
+	struct clk	*clk;
+
+	clk = clk_get(NULL, "gpio");
+	if (IS_ERR(clk)) {
+		printk(KERN_ERR "Error %ld getting gpio clock?\n",
+		       PTR_ERR(clk));
+		return 0;
+	}
+
+	clk_enable(clk);
+
+	for (gpio = 0, irq = gpio_to_irq(0), bank = IRQ_GPIOBNK0;
+	     gpio < DAVINCI_N_GPIO; bank++) {
+		struct gpio_controller	*__iomem g = gpio2controller(gpio);
+		unsigned		i;
+
+		__raw_writel(~0, &g->clr_falling);
+		__raw_writel(~0, &g->clr_rising);
+
+		/* set up all irqs in this bank */
+		set_irq_chained_handler(bank, gpio_irq_handler);
+		set_irq_chip_data(bank, g);
+		set_irq_data(bank, (void *)irq);
+
+		for (i = 0; i < 16 && gpio < DAVINCI_N_GPIO;
+		     i++, irq++, gpio++) {
+			set_irq_chip(irq, &gpio_irqchip);
+			set_irq_chip_data(irq, g);
+			set_irq_handler(irq, handle_simple_irq);
+			set_irq_flags(irq, IRQF_VALID);
+		}
+	}
+
+	/* BINTEN -- per-bank interrupt enable. genirq would also let these
+	 * bits be set/cleared dynamically.
+	 */
+	__raw_writel(0x1f, (void *__iomem)
+		     IO_ADDRESS(DAVINCI_GPIO_BASE + 0x08));
+
+	printk(KERN_INFO "DaVinci: %d gpio irqs\n", irq - gpio_to_irq(0));
+
+	return 0;
+}
+
+arch_initcall(davinci_gpio_irq_setup);
diff --git a/arch/arm/mach-davinci/io.c b/arch/arm/mach-davinci/io.c
index 87fae6f..47787ff 100644
--- a/arch/arm/mach-davinci/io.c
+++ b/arch/arm/mach-davinci/io.c
@@ -17,6 +17,7 @@
 #include <asm/memory.h>
 
 #include <asm/mach/map.h>
+#include <asm/arch/clock.h>
 
 extern void davinci_check_revision(void);
 
@@ -49,3 +50,8 @@
 	 */
 	davinci_check_revision();
 }
+
+void __init davinci_init_common_hw(void)
+{
+	davinci_clk_init();
+}
diff --git a/arch/arm/mach-davinci/mux.c b/arch/arm/mach-davinci/mux.c
new file mode 100644
index 0000000..92d26bd
--- /dev/null
+++ b/arch/arm/mach-davinci/mux.c
@@ -0,0 +1,41 @@
+/*
+ * DaVinci pin multiplexing configurations
+ *
+ * Author: Vladimir Barinov, MontaVista Software, Inc. <source@mvista.com>
+ *
+ * 2007 (c) MontaVista Software, Inc. 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 <linux/io.h>
+#include <linux/spinlock.h>
+
+#include <asm/hardware.h>
+
+#include <asm/arch/mux.h>
+
+/* System control register offsets */
+#define PINMUX0         0x00
+#define PINMUX1         0x04
+
+static DEFINE_SPINLOCK(mux_lock);
+
+void davinci_mux_peripheral(unsigned int mux, unsigned int enable)
+{
+	u32 pinmux, muxreg = PINMUX0;
+
+	if (mux >= DAVINCI_MUX_LEVEL2) {
+		muxreg = PINMUX1;
+		mux -= DAVINCI_MUX_LEVEL2;
+	}
+
+	spin_lock(&mux_lock);
+	pinmux = davinci_readl(DAVINCI_SYSTEM_MODULE_BASE + muxreg);
+	if (enable)
+		pinmux |= (1 << mux);
+	else
+		pinmux &= ~(1 << mux);
+	davinci_writel(pinmux, DAVINCI_SYSTEM_MODULE_BASE + muxreg);
+	spin_unlock(&mux_lock);
+}
diff --git a/arch/arm/mach-davinci/psc.c b/arch/arm/mach-davinci/psc.c
index e1b0050..1334416 100644
--- a/arch/arm/mach-davinci/psc.c
+++ b/arch/arm/mach-davinci/psc.c
@@ -25,39 +25,40 @@
 #include <asm/io.h>
 #include <asm/hardware.h>
 #include <asm/arch/psc.h>
+#include <asm/arch/mux.h>
 
-#define PTCMD	     __REG(0x01C41120)
-#define PDSTAT	     __REG(0x01C41200)
-#define PDCTL1	     __REG(0x01C41304)
-#define EPCPR	     __REG(0x01C41070)
-#define PTSTAT	     __REG(0x01C41128)
+/* PSC register offsets */
+#define EPCPR		0x070
+#define PTCMD		0x120
+#define PTSTAT		0x128
+#define PDSTAT		0x200
+#define PDCTL1		0x304
+#define MDSTAT		0x800
+#define MDCTL		0xA00
 
-#define MDSTAT	     IO_ADDRESS(0x01C41800)
-#define MDCTL	     IO_ADDRESS(0x01C41A00)
-
-#define PINMUX0	     __REG(0x01c40000)
-#define PINMUX1	     __REG(0x01c40004)
-#define VDD3P3V_PWDN __REG(0x01C40048)
+/* System control register offsets */
+#define VDD3P3V_PWDN	0x48
 
 static void davinci_psc_mux(unsigned int id)
 {
 	switch (id) {
 	case DAVINCI_LPSC_ATA:
-		PINMUX0 |= (1 << 17) | (1 << 16);
+		davinci_mux_peripheral(DAVINCI_MUX_HDIREN, 1);
+		davinci_mux_peripheral(DAVINCI_MUX_ATAEN, 1);
 		break;
 	case DAVINCI_LPSC_MMC_SD:
 		/* VDD power manupulations are done in U-Boot for CPMAC
 		 * so applies to MMC as well
 		 */
 		/*Set up the pull regiter for MMC */
-		VDD3P3V_PWDN = 0x0;
-		PINMUX1 &= (~(1 << 9));
+		davinci_writel(0, DAVINCI_SYSTEM_MODULE_BASE + VDD3P3V_PWDN);
+		davinci_mux_peripheral(DAVINCI_MUX_MSTK, 0);
 		break;
 	case DAVINCI_LPSC_I2C:
-		PINMUX1 |= (1 << 7);
+		davinci_mux_peripheral(DAVINCI_MUX_I2C, 1);
 		break;
 	case DAVINCI_LPSC_McBSP:
-		PINMUX1 |= (1 << 10);
+		davinci_mux_peripheral(DAVINCI_MUX_ASP, 1);
 		break;
 	default:
 		break;
@@ -67,33 +68,59 @@
 /* Enable or disable a PSC domain */
 void davinci_psc_config(unsigned int domain, unsigned int id, char enable)
 {
-	volatile unsigned int *mdstat = (unsigned int *)((int)MDSTAT + 4 * id);
-	volatile unsigned int *mdctl = (unsigned int *)((int)MDCTL + 4 * id);
+	u32 epcpr, ptcmd, ptstat, pdstat, pdctl1, mdstat, mdctl, mdstat_mask;
 
 	if (id < 0)
 		return;
 
+	mdctl = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + MDCTL + 4 * id);
 	if (enable)
-		*mdctl |= 0x00000003;	/* Enable Module */
+		mdctl |= 0x00000003;	/* Enable Module */
 	else
-		*mdctl &= 0xFFFFFFF2;	/* Disable Module */
+		mdctl &= 0xFFFFFFF2;	/* Disable Module */
+	davinci_writel(mdctl, DAVINCI_PWR_SLEEP_CNTRL_BASE + MDCTL + 4 * id);
 
-	if ((PDSTAT & 0x00000001) == 0) {
-		PDCTL1 |= 0x1;
-		PTCMD = (1 << domain);
-		while ((((EPCPR >> domain) & 1) == 0));
+	pdstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + PDSTAT);
+	if ((pdstat & 0x00000001) == 0) {
+		pdctl1 = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1);
+		pdctl1 |= 0x1;
+		davinci_writel(pdctl1, DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1);
 
-		PDCTL1 |= 0x100;
-		while (!(((PTSTAT >> domain) & 1) == 0));
+		ptcmd = 1 << domain;
+		davinci_writel(ptcmd, DAVINCI_PWR_SLEEP_CNTRL_BASE + PTCMD);
+
+		do {
+			epcpr = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE +
+					      EPCPR);
+		} while ((((epcpr >> domain) & 1) == 0));
+
+		pdctl1 = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1);
+		pdctl1 |= 0x100;
+		davinci_writel(pdctl1, DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1);
+
+		do {
+			ptstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE +
+					       PTSTAT);
+		} while (!(((ptstat >> domain) & 1) == 0));
 	} else {
-		PTCMD = (1 << domain);
-		while (!(((PTSTAT >> domain) & 1) == 0));
+		ptcmd = 1 << domain;
+		davinci_writel(ptcmd, DAVINCI_PWR_SLEEP_CNTRL_BASE + PTCMD);
+
+		do {
+			ptstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE +
+					       PTSTAT);
+		} while (!(((ptstat >> domain) & 1) == 0));
 	}
 
 	if (enable)
-		while (!((*mdstat & 0x0000001F) == 0x3));
+		mdstat_mask = 0x3;
 	else
-		while (!((*mdstat & 0x0000001F) == 0x2));
+		mdstat_mask = 0x2;
+
+	do {
+		mdstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE +
+				       MDSTAT + 4 * id);
+	} while (!((mdstat & 0x0000001F) == mdstat_mask));
 
 	if (enable)
 		davinci_psc_mux(id);
diff --git a/arch/arm/mach-imx/generic.c b/arch/arm/mach-imx/generic.c
index 1c474cf..a58b678 100644
--- a/arch/arm/mach-imx/generic.c
+++ b/arch/arm/mach-imx/generic.c
@@ -28,12 +28,16 @@
 #include <linux/module.h>
 #include <linux/string.h>
 
+#include <asm/errno.h>
 #include <asm/arch/imxfb.h>
 #include <asm/hardware.h>
 #include <asm/arch/imx-regs.h>
 
 #include <asm/mach/map.h>
 #include <asm/arch/mmc.h>
+#include <asm/arch/gpio.h>
+
+unsigned long imx_gpio_alloc_map[(GPIO_PORT_MAX + 1) * 32 / BITS_PER_LONG];
 
 void imx_gpio_mode(int gpio_mode)
 {
@@ -95,6 +99,120 @@
 
 EXPORT_SYMBOL(imx_gpio_mode);
 
+int imx_gpio_request(unsigned gpio, const char *label)
+{
+	if(gpio >= (GPIO_PORT_MAX + 1) * 32)
+		printk(KERN_ERR "imx_gpio: Attempt to request nonexistent GPIO %d for \"%s\"\n",
+			gpio, label ? label : "?");
+		return -EINVAL;
+
+	if(test_and_set_bit(gpio, imx_gpio_alloc_map)) {
+		printk(KERN_ERR "imx_gpio: GPIO %d already used. Allocation for \"%s\" failed\n",
+			gpio, label ? label : "?");
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
+EXPORT_SYMBOL(imx_gpio_request);
+
+void imx_gpio_free(unsigned gpio)
+{
+	if(gpio >= (GPIO_PORT_MAX + 1) * 32)
+		return;
+
+	clear_bit(gpio, imx_gpio_alloc_map);
+}
+
+EXPORT_SYMBOL(imx_gpio_free);
+
+int imx_gpio_direction_input(unsigned gpio)
+{
+	imx_gpio_mode(gpio| GPIO_IN);
+	return 0;
+}
+
+EXPORT_SYMBOL(imx_gpio_direction_input);
+
+int imx_gpio_direction_output(unsigned gpio, int value)
+{
+	imx_gpio_set_value(gpio, value);
+	imx_gpio_mode(gpio| GPIO_OUT);
+	return 0;
+}
+
+EXPORT_SYMBOL(imx_gpio_direction_output);
+
+int imx_gpio_setup_multiple_pins(const int *pin_list, unsigned count,
+				int alloc_mode, const char *label)
+{
+	const int *p = pin_list;
+	int i;
+	unsigned gpio;
+	unsigned mode;
+
+	for (i = 0; i < count; i++) {
+		gpio = *p & (GPIO_PIN_MASK | GPIO_PORT_MASK);
+		mode = *p & ~(GPIO_PIN_MASK | GPIO_PORT_MASK);
+
+		if (gpio >= (GPIO_PORT_MAX + 1) * 32)
+			goto setup_error;
+
+		if (alloc_mode & IMX_GPIO_ALLOC_MODE_RELEASE)
+			imx_gpio_free(gpio);
+		else if (!(alloc_mode & IMX_GPIO_ALLOC_MODE_NO_ALLOC))
+			if (imx_gpio_request(gpio, label))
+				if (!(alloc_mode & IMX_GPIO_ALLOC_MODE_TRY_ALLOC))
+					goto setup_error;
+
+		if (!(alloc_mode & (IMX_GPIO_ALLOC_MODE_ALLOC_ONLY |
+				    IMX_GPIO_ALLOC_MODE_RELEASE)))
+			imx_gpio_mode(gpio | mode);
+
+		p++;
+	}
+	return 0;
+
+setup_error:
+	if(alloc_mode & (IMX_GPIO_ALLOC_MODE_NO_ALLOC |
+		         IMX_GPIO_ALLOC_MODE_TRY_ALLOC))
+		return -EINVAL;
+
+	while (p != pin_list) {
+		p--;
+		gpio = *p & (GPIO_PIN_MASK | GPIO_PORT_MASK);
+		imx_gpio_free(gpio);
+	}
+
+	return -EINVAL;
+}
+
+EXPORT_SYMBOL(imx_gpio_setup_multiple_pins);
+
+void __imx_gpio_set_value(unsigned gpio, int value)
+{
+	imx_gpio_set_value_inline(gpio, value);
+}
+
+EXPORT_SYMBOL(__imx_gpio_set_value);
+
+int imx_gpio_to_irq(unsigned gpio)
+{
+	return IRQ_GPIOA(0) + gpio;
+}
+
+EXPORT_SYMBOL(imx_gpio_to_irq);
+
+int imx_irq_to_gpio(unsigned irq)
+{
+	if (irq < IRQ_GPIOA(0))
+		return -EINVAL;
+	return irq - IRQ_GPIOA(0);
+}
+
+EXPORT_SYMBOL(imx_irq_to_gpio);
+
 /*
  *  get the system pll clock in Hz
  *
diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c
index 6960a9d..010f6fa 100644
--- a/arch/arm/mach-imx/time.c
+++ b/arch/arm/mach-imx/time.c
@@ -3,6 +3,7 @@
  *
  *  Copyright (C) 2000-2001 Deep Blue Solutions
  *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
+ *  Copyright (C) 2006-2007 Pavel Pisa (ppisa@pikron.com)
  *
  * 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
@@ -15,6 +16,7 @@
 #include <linux/irq.h>
 #include <linux/time.h>
 #include <linux/clocksource.h>
+#include <linux/clockchips.h>
 
 #include <asm/hardware.h>
 #include <asm/io.h>
@@ -25,7 +27,8 @@
 /* Use timer 1 as system timer */
 #define TIMER_BASE IMX_TIM1_BASE
 
-static unsigned long evt_diff;
+static struct clock_event_device clockevent_imx;
+static enum clock_event_mode clockevent_mode = CLOCK_EVT_MODE_UNUSED;
 
 /*
  * IRQ handler for the timer
@@ -33,25 +36,20 @@
 static irqreturn_t
 imx_timer_interrupt(int irq, void *dev_id)
 {
+	struct clock_event_device *evt = &clockevent_imx;
 	uint32_t tstat;
+	irqreturn_t ret = IRQ_NONE;
 
 	/* clear the interrupt */
 	tstat = IMX_TSTAT(TIMER_BASE);
 	IMX_TSTAT(TIMER_BASE) = 0;
 
 	if (tstat & TSTAT_COMP) {
-		do {
-
-			write_seqlock(&xtime_lock);
-			timer_tick();
-			write_sequnlock(&xtime_lock);
-			IMX_TCMP(TIMER_BASE) += evt_diff;
-
-		} while (unlikely((int32_t)(IMX_TCMP(TIMER_BASE)
-					- IMX_TCN(TIMER_BASE)) < 0));
+		evt->event_handler(evt);
+		ret = IRQ_HANDLED;
 	}
 
-	return IRQ_HANDLED;
+	return ret;
 }
 
 static struct irqaction imx_timer_irq = {
@@ -70,10 +68,8 @@
 	 */
 	IMX_TCTL(TIMER_BASE) = 0;
 	IMX_TPRER(TIMER_BASE) = 0;
-	IMX_TCMP(TIMER_BASE) = LATCH - 1;
 
-	IMX_TCTL(TIMER_BASE) = TCTL_FRR | TCTL_CLK_PCLK1 | TCTL_IRQEN | TCTL_TEN;
-	evt_diff = LATCH;
+	IMX_TCTL(TIMER_BASE) = TCTL_FRR | TCTL_CLK_PCLK1 | TCTL_TEN;
 }
 
 cycle_t imx_get_cycles(void)
@@ -99,11 +95,108 @@
 	return 0;
 }
 
+static int imx_set_next_event(unsigned long evt,
+				  struct clock_event_device *unused)
+{
+	unsigned long tcmp;
+
+	tcmp = IMX_TCN(TIMER_BASE) + evt;
+	IMX_TCMP(TIMER_BASE) = tcmp;
+
+	return (int32_t)(tcmp - IMX_TCN(TIMER_BASE)) < 0 ? -ETIME : 0;
+}
+
+#ifdef DEBUG
+static const char *clock_event_mode_label[]={
+	[CLOCK_EVT_MODE_PERIODIC] = "CLOCK_EVT_MODE_PERIODIC",
+	[CLOCK_EVT_MODE_ONESHOT]  = "CLOCK_EVT_MODE_ONESHOT",
+	[CLOCK_EVT_MODE_SHUTDOWN] = "CLOCK_EVT_MODE_SHUTDOWN",
+	[CLOCK_EVT_MODE_UNUSED]   = "CLOCK_EVT_MODE_UNUSED"
+};
+#endif /*DEBUG*/
+
+static void imx_set_mode(enum clock_event_mode mode, struct clock_event_device *evt)
+{
+	unsigned long flags;
+
+	/*
+	 * The timer interrupt generation is disabled at least
+	 * for enough time to call imx_set_next_event()
+	 */
+	local_irq_save(flags);
+	/* Disable interrupt in GPT module */
+	IMX_TCTL(TIMER_BASE) &= ~TCTL_IRQEN;
+	if (mode != clockevent_mode) {
+		/* Set event time into far-far future */
+		IMX_TCMP(TIMER_BASE) = IMX_TCN(TIMER_BASE) - 3;
+		/* Clear pending interrupt */
+		IMX_TSTAT(TIMER_BASE) &= ~TSTAT_COMP;
+	}
+
+#ifdef DEBUG
+	printk(KERN_INFO "imx_set_mode: changing mode from %s to %s\n",
+		clock_event_mode_label[clockevent_mode], clock_event_mode_label[mode]);
+#endif /*DEBUG*/
+
+	/* Remember timer mode */
+	clockevent_mode = mode;
+	local_irq_restore(flags);
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		printk(KERN_ERR "imx_set_mode: Periodic mode is not supported for i.MX\n");
+		break;
+	case CLOCK_EVT_MODE_ONESHOT:
+		/*
+		 * Do not put overhead of interrupt enable/disable into
+		 * imx_set_next_event(), the core has about 4 minutes
+		 * to call imx_set_next_event() or shutdown clock after
+		 * mode switching
+		 */
+		local_irq_save(flags);
+		IMX_TCTL(TIMER_BASE) |= TCTL_IRQEN;
+		local_irq_restore(flags);
+		break;
+	case CLOCK_EVT_MODE_SHUTDOWN:
+	case CLOCK_EVT_MODE_UNUSED:
+		/* Left event sources disabled, no more interrupts appears */
+		break;
+	}
+}
+
+static struct clock_event_device clockevent_imx = {
+	.name		= "imx_timer1",
+	.features	= CLOCK_EVT_FEAT_ONESHOT,
+	.shift		= 32,
+	.set_mode	= imx_set_mode,
+	.set_next_event	= imx_set_next_event,
+	.rating		= 200,
+};
+
+static int __init imx_clockevent_init(void)
+{
+	clockevent_imx.mult = div_sc(imx_get_perclk1(), NSEC_PER_SEC,
+					clockevent_imx.shift);
+	clockevent_imx.max_delta_ns =
+		clockevent_delta2ns(0xfffffffe, &clockevent_imx);
+	clockevent_imx.min_delta_ns =
+		clockevent_delta2ns(0xf, &clockevent_imx);
+
+	clockevent_imx.cpumask = cpumask_of_cpu(0);
+
+	clockevents_register_device(&clockevent_imx);
+
+	return 0;
+}
+
+
 static void __init imx_timer_init(void)
 {
 	imx_timer_hardware_init();
 	imx_clocksource_init();
 
+	imx_clockevent_init();
+
 	/*
 	 * Make irqs happen for the system timer
 	 */
diff --git a/arch/arm/mach-iop13xx/tpmi.c b/arch/arm/mach-iop13xx/tpmi.c
index d3dc278..2476347 100644
--- a/arch/arm/mach-iop13xx/tpmi.c
+++ b/arch/arm/mach-iop13xx/tpmi.c
@@ -29,13 +29,15 @@
 #define IOP13XX_TPMI_MMR(dev) 	IOP13XX_REG_ADDR32_PHYS(0x48000 + (dev << 12))
 #define IOP13XX_TPMI_MEM(dev) 	IOP13XX_REG_ADDR32_PHYS(0x60000 + (dev << 13))
 #define IOP13XX_TPMI_CTRL(dev)	IOP13XX_REG_ADDR32_PHYS(0x50000 + (dev << 10))
+#define IOP13XX_TPMI_IOP_CTRL(dev) (IOP13XX_TPMI_CTRL(dev) + 0x2000)
 #define IOP13XX_TPMI_MMR_SIZE	    (SZ_4K - 1)
 #define IOP13XX_TPMI_MEM_SIZE	    (255)
 #define IOP13XX_TPMI_MEM_CTRL	    (SZ_1K - 1)
 #define IOP13XX_TPMI_RESOURCE_MMR  0
 #define IOP13XX_TPMI_RESOURCE_MEM  1
 #define IOP13XX_TPMI_RESOURCE_CTRL 2
-#define IOP13XX_TPMI_RESOURCE_IRQ  3
+#define IOP13XX_TPMI_RESOURCE_IOP_CTRL 3
+#define IOP13XX_TPMI_RESOURCE_IRQ  4
 
 static struct resource iop13xx_tpmi_0_resources[] = {
 	[IOP13XX_TPMI_RESOURCE_MMR] = {
@@ -53,6 +55,11 @@
 		.end = IOP13XX_TPMI_CTRL(0) + IOP13XX_TPMI_MEM_CTRL,
 		.flags = IORESOURCE_MEM,
 	},
+	[IOP13XX_TPMI_RESOURCE_IOP_CTRL] = {
+		.start = IOP13XX_TPMI_IOP_CTRL(0),
+		.end = IOP13XX_TPMI_IOP_CTRL(0) + IOP13XX_TPMI_MEM_CTRL,
+		.flags = IORESOURCE_MEM,
+	},
 	[IOP13XX_TPMI_RESOURCE_IRQ] = {
 		.start = IRQ_IOP13XX_TPMI0_OUT,
 		.end = IRQ_IOP13XX_TPMI0_OUT,
@@ -76,6 +83,11 @@
 		.end = IOP13XX_TPMI_CTRL(1) + IOP13XX_TPMI_MEM_CTRL,
 		.flags = IORESOURCE_MEM,
 	},
+	[IOP13XX_TPMI_RESOURCE_IOP_CTRL] = {
+		.start = IOP13XX_TPMI_IOP_CTRL(1),
+		.end = IOP13XX_TPMI_IOP_CTRL(1) + IOP13XX_TPMI_MEM_CTRL,
+		.flags = IORESOURCE_MEM,
+	},
 	[IOP13XX_TPMI_RESOURCE_IRQ] = {
 		.start = IRQ_IOP13XX_TPMI1_OUT,
 		.end = IRQ_IOP13XX_TPMI1_OUT,
@@ -99,6 +111,11 @@
 		.end = IOP13XX_TPMI_CTRL(2) + IOP13XX_TPMI_MEM_CTRL,
 		.flags = IORESOURCE_MEM,
 	},
+	[IOP13XX_TPMI_RESOURCE_IOP_CTRL] = {
+		.start = IOP13XX_TPMI_IOP_CTRL(2),
+		.end = IOP13XX_TPMI_IOP_CTRL(2) + IOP13XX_TPMI_MEM_CTRL,
+		.flags = IORESOURCE_MEM,
+	},
 	[IOP13XX_TPMI_RESOURCE_IRQ] = {
 		.start = IRQ_IOP13XX_TPMI2_OUT,
 		.end = IRQ_IOP13XX_TPMI2_OUT,
@@ -122,6 +139,11 @@
 		.end = IOP13XX_TPMI_CTRL(3) + IOP13XX_TPMI_MEM_CTRL,
 		.flags = IORESOURCE_MEM,
 	},
+	[IOP13XX_TPMI_RESOURCE_IOP_CTRL] = {
+		.start = IOP13XX_TPMI_IOP_CTRL(3),
+		.end = IOP13XX_TPMI_IOP_CTRL(3) + IOP13XX_TPMI_MEM_CTRL,
+		.flags = IORESOURCE_MEM,
+	},
 	[IOP13XX_TPMI_RESOURCE_IRQ] = {
 		.start = IRQ_IOP13XX_TPMI3_OUT,
 		.end = IRQ_IOP13XX_TPMI3_OUT,
@@ -133,7 +155,7 @@
 static struct platform_device iop13xx_tpmi_0_device = {
 	.name = "iop-tpmi",
 	.id = 0,
-	.num_resources = 4,
+	.num_resources = ARRAY_SIZE(iop13xx_tpmi_0_resources),
 	.resource = iop13xx_tpmi_0_resources,
 	.dev = {
 		.dma_mask          = &iop13xx_tpmi_mask,
@@ -144,7 +166,7 @@
 static struct platform_device iop13xx_tpmi_1_device = {
 	.name = "iop-tpmi",
 	.id = 1,
-	.num_resources = 4,
+	.num_resources = ARRAY_SIZE(iop13xx_tpmi_1_resources),
 	.resource = iop13xx_tpmi_1_resources,
 	.dev = {
 		.dma_mask          = &iop13xx_tpmi_mask,
@@ -155,7 +177,7 @@
 static struct platform_device iop13xx_tpmi_2_device = {
 	.name = "iop-tpmi",
 	.id = 2,
-	.num_resources = 4,
+	.num_resources = ARRAY_SIZE(iop13xx_tpmi_2_resources),
 	.resource = iop13xx_tpmi_2_resources,
 	.dev = {
 		.dma_mask          = &iop13xx_tpmi_mask,
@@ -166,7 +188,7 @@
 static struct platform_device iop13xx_tpmi_3_device = {
 	.name = "iop-tpmi",
 	.id = 3,
-	.num_resources = 4,
+	.num_resources = ARRAY_SIZE(iop13xx_tpmi_3_resources),
 	.resource = iop13xx_tpmi_3_resources,
 	.dev = {
 		.dma_mask          = &iop13xx_tpmi_mask,
diff --git a/arch/arm/mach-ixp4xx/Kconfig b/arch/arm/mach-ixp4xx/Kconfig
index 0609098..61b2dfc 100644
--- a/arch/arm/mach-ixp4xx/Kconfig
+++ b/arch/arm/mach-ixp4xx/Kconfig
@@ -41,6 +41,22 @@
 	  Engineering Coyote Gateway Reference Platform. For more
 	  information on this platform, see <file:Documentation/arm/IXP4xx>.
 
+config MACH_GATEWAY7001
+	bool "Gateway 7001"
+	select PCI
+	help
+	  Say 'Y' here if you want your kernel to support Gateway's
+	  7001 Access Point. For more information on this platform,
+	  see http://openwrt.org
+
+config MACH_WG302V2
+	bool "Netgear WG302 v2 / WAG302 v2"
+	select PCI
+	help
+	  Say 'Y' here if you want your kernel to support Netgear's
+	  WG302 v2 or WAG302 v2 Access Points. For more information
+	  on this platform, see http://openwrt.org
+
 config ARCH_IXDP425
 	bool "IXDP425"
 	help
diff --git a/arch/arm/mach-ixp4xx/Makefile b/arch/arm/mach-ixp4xx/Makefile
index 3b87c47..77e00ad 100644
--- a/arch/arm/mach-ixp4xx/Makefile
+++ b/arch/arm/mach-ixp4xx/Makefile
@@ -13,6 +13,8 @@
 obj-pci-$(CONFIG_MACH_NSLU2)		+= nslu2-pci.o
 obj-pci-$(CONFIG_MACH_NAS100D)		+= nas100d-pci.o
 obj-pci-$(CONFIG_MACH_DSMG600)		+= dsmg600-pci.o
+obj-pci-$(CONFIG_MACH_GATEWAY7001)	+= gateway7001-pci.o
+obj-pci-$(CONFIG_MACH_WG302V2)		+= wg302v2-pci.o
 
 obj-y	+= common.o
 
@@ -24,5 +26,7 @@
 obj-$(CONFIG_MACH_NSLU2)	+= nslu2-setup.o nslu2-power.o
 obj-$(CONFIG_MACH_NAS100D)	+= nas100d-setup.o nas100d-power.o
 obj-$(CONFIG_MACH_DSMG600)      += dsmg600-setup.o dsmg600-power.o
+obj-$(CONFIG_MACH_GATEWAY7001)	+= gateway7001-setup.o
+obj-$(CONFIG_MACH_WG302V2)	+= wg302v2-setup.o
 
 obj-$(CONFIG_PCI)		+= $(obj-pci-$(CONFIG_PCI)) common-pci.o
diff --git a/arch/arm/mach-ixp4xx/gateway7001-pci.c b/arch/arm/mach-ixp4xx/gateway7001-pci.c
new file mode 100644
index 0000000..6abf568
--- /dev/null
+++ b/arch/arm/mach-ixp4xx/gateway7001-pci.c
@@ -0,0 +1,63 @@
+/*
+ * arch/arch/mach-ixp4xx/gateway7001-pci.c
+ *
+ * PCI setup routines for Gateway 7001
+ *
+ * Copyright (C) 2007 Imre Kaloz <kaloz@openwrt.org>
+ *
+ * based on coyote-pci.c:
+ *	Copyright (C) 2002 Jungo Software Technologies.
+ *	Copyright (C) 2003 MontaVista Softwrae, Inc.
+ *
+ * Maintainer: Imre Kaloz <kaloz@openwrt.org>
+ *
+ * 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/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+
+#include <asm/mach/pci.h>
+
+void __init gateway7001_pci_preinit(void)
+{
+	set_irq_type(IRQ_IXP4XX_GPIO10, IRQT_LOW);
+	set_irq_type(IRQ_IXP4XX_GPIO11, IRQT_LOW);
+
+	ixp4xx_pci_preinit();
+}
+
+static int __init gateway7001_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	if (slot == 1)
+		return IRQ_IXP4XX_GPIO11;
+	else if (slot == 2)
+		return IRQ_IXP4XX_GPIO10;
+	else return -1;
+}
+
+struct hw_pci gateway7001_pci __initdata = {
+	.nr_controllers = 1,
+	.preinit =        gateway7001_pci_preinit,
+	.swizzle =        pci_std_swizzle,
+	.setup =          ixp4xx_setup,
+	.scan =           ixp4xx_scan_bus,
+	.map_irq =        gateway7001_map_irq,
+};
+
+int __init gateway7001_pci_init(void)
+{
+	if (machine_is_gateway7001())
+		pci_common_init(&gateway7001_pci);
+	return 0;
+}
+
+subsys_initcall(gateway7001_pci_init);
diff --git a/arch/arm/mach-ixp4xx/gateway7001-setup.c b/arch/arm/mach-ixp4xx/gateway7001-setup.c
new file mode 100644
index 0000000..3787683
--- /dev/null
+++ b/arch/arm/mach-ixp4xx/gateway7001-setup.c
@@ -0,0 +1,108 @@
+/*
+ * arch/arm/mach-ixp4xx/gateway7001-setup.c
+ *
+ * Board setup for the Gateway 7001 board
+ *
+ * Copyright (C) 2007 Imre Kaloz <kaloz@openwrt.org>
+ *
+ * based on coyote-setup.c:
+ *      Copyright (C) 2003-2005 MontaVista Software, Inc.
+ *
+ * Author: Imre Kaloz <Kaloz@openwrt.org>
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/serial_8250.h>
+#include <linux/slab.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+
+static struct flash_platform_data gateway7001_flash_data = {
+	.map_name	= "cfi_probe",
+	.width		= 2,
+};
+
+static struct resource gateway7001_flash_resource = {
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device gateway7001_flash = {
+	.name		= "IXP4XX-Flash",
+	.id		= 0,
+	.dev		= {
+		.platform_data = &gateway7001_flash_data,
+	},
+	.num_resources	= 1,
+	.resource	= &gateway7001_flash_resource,
+};
+
+static struct resource gateway7001_uart_resource = {
+	.start	= IXP4XX_UART2_BASE_PHYS,
+	.end	= IXP4XX_UART2_BASE_PHYS + 0x0fff,
+	.flags	= IORESOURCE_MEM,
+};
+
+static struct plat_serial8250_port gateway7001_uart_data[] = {
+	{
+		.mapbase	= IXP4XX_UART2_BASE_PHYS,
+		.membase	= (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
+		.irq		= IRQ_IXP4XX_UART2,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= IXP4XX_UART_XTAL,
+	},
+	{ },
+};
+
+static struct platform_device gateway7001_uart = {
+	.name		= "serial8250",
+	.id		= PLAT8250_DEV_PLATFORM,
+	.dev			= {
+		.platform_data	= gateway7001_uart_data,
+	},
+	.num_resources	= 1,
+	.resource	= &gateway7001_uart_resource,
+};
+
+static struct platform_device *gateway7001_devices[] __initdata = {
+	&gateway7001_flash,
+	&gateway7001_uart
+};
+
+static void __init gateway7001_init(void)
+{
+	ixp4xx_sys_init();
+
+	gateway7001_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
+	gateway7001_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_32M - 1;
+
+	*IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE;
+	*IXP4XX_EXP_CS1 = *IXP4XX_EXP_CS0;
+
+	platform_add_devices(gateway7001_devices, ARRAY_SIZE(gateway7001_devices));
+}
+
+#ifdef CONFIG_MACH_GATEWAY7001
+MACHINE_START(GATEWAY7001, "Gateway 7001 AP")
+	/* Maintainer: Imre Kaloz <kaloz@openwrt.org> */
+	.phys_io	= IXP4XX_PERIPHERAL_BASE_PHYS,
+	.io_pg_offst	= ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
+	.map_io		= ixp4xx_map_io,
+	.init_irq	= ixp4xx_init_irq,
+	.timer		= &ixp4xx_timer,
+	.boot_params	= 0x0100,
+	.init_machine	= gateway7001_init,
+MACHINE_END
+#endif
diff --git a/arch/arm/mach-ixp4xx/gtwx5715-pci.c b/arch/arm/mach-ixp4xx/gtwx5715-pci.c
index a66484b6..0d5a424 100644
--- a/arch/arm/mach-ixp4xx/gtwx5715-pci.c
+++ b/arch/arm/mach-ixp4xx/gtwx5715-pci.c
@@ -25,17 +25,13 @@
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/irq.h>
+
 #include <asm/mach-types.h>
 #include <asm/hardware.h>
-#include <asm/irq.h>
 #include <asm/arch/gtwx5715.h>
 #include <asm/mach/pci.h>
 
-extern void ixp4xx_pci_preinit(void);
-extern int ixp4xx_setup(int nr, struct pci_sys_data *sys);
-extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys);
-
-
 /*
  * The exact GPIO pins and IRQs are defined in arch-ixp4xx/gtwx5715.h
  * Slot 0 isn't actually populated with a card connector but
diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c
index ec4f079..d5008d8 100644
--- a/arch/arm/mach-ixp4xx/ixdp425-setup.c
+++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c
@@ -15,6 +15,10 @@
 #include <linux/tty.h>
 #include <linux/serial_8250.h>
 #include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
 
 #include <asm/types.h>
 #include <asm/setup.h>
@@ -24,6 +28,7 @@
 #include <asm/irq.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
+#include <asm/delay.h>
 
 static struct flash_platform_data ixdp425_flash_data = {
 	.map_name	= "cfi_probe",
@@ -44,6 +49,77 @@
 	.resource	= &ixdp425_flash_resource,
 };
 
+#if defined(CONFIG_MTD_NAND_PLATFORM) || \
+    defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
+
+#ifdef CONFIG_MTD_PARTITIONS
+const char *part_probes[] = { "cmdlinepart", NULL };
+
+static struct mtd_partition ixdp425_partitions[] = {
+	{
+		.name	= "ixp400 NAND FS 0",
+		.offset	= 0,
+		.size 	= SZ_8M
+	}, {
+		.name	= "ixp400 NAND FS 1",
+		.offset	= MTDPART_OFS_APPEND,
+		.size	= MTDPART_SIZ_FULL
+	},
+};
+#endif
+
+static void
+ixdp425_flash_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+{
+	struct nand_chip *this = mtd->priv;
+	int offset = (int)this->priv;
+
+	if (ctrl & NAND_CTRL_CHANGE) {
+		if (ctrl & NAND_NCE) {
+			gpio_line_set(IXDP425_NAND_NCE_PIN, IXP4XX_GPIO_LOW);
+			udelay(5);
+		} else
+			gpio_line_set(IXDP425_NAND_NCE_PIN, IXP4XX_GPIO_HIGH);
+
+		offset = (ctrl & NAND_CLE) ? IXDP425_NAND_CMD_BYTE : 0;
+		offset |= (ctrl & NAND_ALE) ? IXDP425_NAND_ADDR_BYTE : 0;
+		this->priv = (void *)offset;
+	}
+
+	if (cmd != NAND_CMD_NONE)
+		writeb(cmd, this->IO_ADDR_W + offset);
+}
+
+static struct platform_nand_data ixdp425_flash_nand_data = {
+	.chip = {
+		.chip_delay		= 30,
+		.options		= NAND_NO_AUTOINCR,
+#ifdef CONFIG_MTD_PARTITIONS
+		.part_probe_types 	= part_probes,
+		.partitions	 	= ixdp425_partitions,
+		.nr_partitions	 	= ARRAY_SIZE(ixdp425_partitions),
+#endif
+	},
+	.ctrl = {
+		.cmd_ctrl 		= ixdp425_flash_nand_cmd_ctrl
+	}
+};
+
+static struct resource ixdp425_flash_nand_resource = {
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device ixdp425_flash_nand = {
+	.name		= "gen_nand",
+	.id		= -1,
+	.dev		= {
+		.platform_data = &ixdp425_flash_nand_data,
+	},
+	.num_resources	= 1,
+	.resource	= &ixdp425_flash_nand_resource,
+};
+#endif	/* CONFIG_MTD_NAND_PLATFORM */
+
 static struct ixp4xx_i2c_pins ixdp425_i2c_gpio_pins = {
 	.sda_pin	= IXDP425_SDA_PIN,
 	.scl_pin	= IXDP425_SCL_PIN,
@@ -104,6 +180,10 @@
 static struct platform_device *ixdp425_devices[] __initdata = {
 	&ixdp425_i2c_controller,
 	&ixdp425_flash,
+#if defined(CONFIG_MTD_NAND_PLATFORM) || \
+    defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
+	&ixdp425_flash_nand,
+#endif
 	&ixdp425_uart
 };
 
@@ -115,6 +195,22 @@
 	ixdp425_flash_resource.end =
 		IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
 
+#if defined(CONFIG_MTD_NAND_PLATFORM) || \
+    defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
+	ixdp425_flash_nand_resource.start = IXP4XX_EXP_BUS_BASE(3),
+	ixdp425_flash_nand_resource.end   = IXP4XX_EXP_BUS_BASE(3) + 0x10 - 1;
+
+	gpio_line_config(IXDP425_NAND_NCE_PIN, IXP4XX_GPIO_OUT);
+
+	/* Configure expansion bus for NAND Flash */
+	*IXP4XX_EXP_CS3 = IXP4XX_EXP_BUS_CS_EN |
+			  IXP4XX_EXP_BUS_STROBE_T(1) |	/* extend by 1 clock */
+			  IXP4XX_EXP_BUS_CYCLES(0) |	/* Intel cycles */
+			  IXP4XX_EXP_BUS_SIZE(0) |	/* 512bytes addr space*/
+			  IXP4XX_EXP_BUS_WR_EN |
+			  IXP4XX_EXP_BUS_BYTE_EN;	/* 8 bit data bus */
+#endif
+
 	if (cpu_is_ixp43x()) {
 		ixdp425_uart.num_resources = 1;
 		ixdp425_uart_data[1].flags = 0;
diff --git a/arch/arm/mach-ixp4xx/wg302v2-pci.c b/arch/arm/mach-ixp4xx/wg302v2-pci.c
new file mode 100644
index 0000000..6588f2c
--- /dev/null
+++ b/arch/arm/mach-ixp4xx/wg302v2-pci.c
@@ -0,0 +1,63 @@
+/*
+ * arch/arch/mach-ixp4xx/wg302v2-pci.c
+ *
+ * PCI setup routines for the Netgear WG302 v2 and WAG302 v2
+ *
+ * Copyright (C) 2007 Imre Kaloz <kaloz@openwrt.org>
+ *
+ * based on coyote-pci.c:
+ *	Copyright (C) 2002 Jungo Software Technologies.
+ *	Copyright (C) 2003 MontaVista Software, Inc.
+ *
+ * Maintainer: Imre Kaloz <kaloz@openwrt.org>
+ *
+ * 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/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+
+#include <asm/mach/pci.h>
+
+void __init wg302v2_pci_preinit(void)
+{
+	set_irq_type(IRQ_IXP4XX_GPIO8, IRQT_LOW);
+	set_irq_type(IRQ_IXP4XX_GPIO9, IRQT_LOW);
+
+	ixp4xx_pci_preinit();
+}
+
+static int __init wg302v2_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	if (slot == 1)
+		return IRQ_IXP4XX_GPIO8;
+	else if (slot == 2)
+		return IRQ_IXP4XX_GPIO9;
+	else return -1;
+}
+
+struct hw_pci wg302v2_pci __initdata = {
+	.nr_controllers = 1,
+	.preinit =        wg302v2_pci_preinit,
+	.swizzle =        pci_std_swizzle,
+	.setup =          ixp4xx_setup,
+	.scan =           ixp4xx_scan_bus,
+	.map_irq =        wg302v2_map_irq,
+};
+
+int __init wg302v2_pci_init(void)
+{
+	if (machine_is_wg302v2())
+		pci_common_init(&wg302v2_pci);
+	return 0;
+}
+
+subsys_initcall(wg302v2_pci_init);
diff --git a/arch/arm/mach-ixp4xx/wg302v2-setup.c b/arch/arm/mach-ixp4xx/wg302v2-setup.c
new file mode 100644
index 0000000..f7e09ad
--- /dev/null
+++ b/arch/arm/mach-ixp4xx/wg302v2-setup.c
@@ -0,0 +1,109 @@
+/*
+ * arch/arm/mach-ixp4xx/wg302-setup.c
+ *
+ * Board setup for the Netgear WG302 v2 and WAG302 v2
+ *
+ * Copyright (C) 2007 Imre Kaloz <Kaloz@openwrt.org>
+ *
+ * based on coyote-setup.c:
+ *      Copyright (C) 2003-2005 MontaVista Software, Inc.
+ *
+ * Author: Imre Kaloz <kaloz@openwrt.org>
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/serial_8250.h>
+#include <linux/slab.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+
+static struct flash_platform_data wg302v2_flash_data = {
+	.map_name	= "cfi_probe",
+	.width		= 2,
+};
+
+static struct resource wg302v2_flash_resource = {
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device wg302v2_flash = {
+	.name		= "IXP4XX-Flash",
+	.id		= 0,
+	.dev		= {
+		.platform_data = &wg302v2_flash_data,
+	},
+	.num_resources	= 1,
+	.resource	= &wg302v2_flash_resource,
+};
+
+static struct resource wg302v2_uart_resource = {
+	.start	= IXP4XX_UART2_BASE_PHYS,
+	.end	= IXP4XX_UART2_BASE_PHYS + 0x0fff,
+	.flags	= IORESOURCE_MEM,
+};
+
+static struct plat_serial8250_port wg302v2_uart_data[] = {
+	{
+		.mapbase	= IXP4XX_UART2_BASE_PHYS,
+		.membase	= (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
+		.irq		= IRQ_IXP4XX_UART2,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= IXP4XX_UART_XTAL,
+	},
+	{ },
+};
+
+static struct platform_device wg302v2_uart = {
+	.name		= "serial8250",
+	.id		= PLAT8250_DEV_PLATFORM,
+	.dev			= {
+		.platform_data	= wg302v2_uart_data,
+	},
+	.num_resources	= 1,
+	.resource	= &wg302v2_uart_resource,
+};
+
+static struct platform_device *wg302v2_devices[] __initdata = {
+	&wg302v2_flash,
+	&wg302v2_uart,
+};
+
+static void __init wg302v2_init(void)
+{
+	ixp4xx_sys_init();
+
+	wg302v2_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
+	wg302v2_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_32M - 1;
+
+	*IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE;
+	*IXP4XX_EXP_CS1 = *IXP4XX_EXP_CS0;
+
+	platform_add_devices(wg302v2_devices, ARRAY_SIZE(wg302v2_devices));
+}
+
+#ifdef CONFIG_MACH_WG302V2
+MACHINE_START(WG302V2, "Netgear WG302 v2 / WAG302 v2")
+	/* Maintainer: Imre Kaloz <kaloz@openwrt.org> */
+	.phys_io	= IXP4XX_PERIPHERAL_BASE_PHYS,
+	.io_pg_offst	= ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
+	.map_io		= ixp4xx_map_io,
+	.init_irq	= ixp4xx_init_irq,
+	.timer		= &ixp4xx_timer,
+	.boot_params	= 0x0100,
+	.init_machine	= wg302v2_init,
+MACHINE_END
+#endif
diff --git a/arch/arm/mach-pxa/clock.c b/arch/arm/mach-pxa/clock.c
index 8f7c90a..34a31ca 100644
--- a/arch/arm/mach-pxa/clock.c
+++ b/arch/arm/mach-pxa/clock.c
@@ -12,7 +12,6 @@
 
 #include <asm/arch/pxa-regs.h>
 #include <asm/hardware.h>
-#include <asm/semaphore.h>
 
 struct clk {
 	struct list_head	node;
@@ -25,21 +24,21 @@
 };
 
 static LIST_HEAD(clocks);
-static DECLARE_MUTEX(clocks_sem);
+static DEFINE_MUTEX(clocks_mutex);
 static DEFINE_SPINLOCK(clocks_lock);
 
 struct clk *clk_get(struct device *dev, const char *id)
 {
 	struct clk *p, *clk = ERR_PTR(-ENOENT);
 
-	down(&clocks_sem);
+	mutex_lock(&clocks_mutex);
 	list_for_each_entry(p, &clocks, node) {
 		if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
 			clk = p;
 			break;
 		}
 	}
-	up(&clocks_sem);
+	mutex_unlock(&clocks_mutex);
 
 	return clk;
 }
@@ -101,18 +100,18 @@
 
 int clk_register(struct clk *clk)
 {
-	down(&clocks_sem);
+	mutex_lock(&clocks_mutex);
 	list_add(&clk->node, &clocks);
-	up(&clocks_sem);
+	mutex_unlock(&clocks_mutex);
 	return 0;
 }
 EXPORT_SYMBOL(clk_register);
 
 void clk_unregister(struct clk *clk)
 {
-	down(&clocks_sem);
+	mutex_lock(&clocks_mutex);
 	list_del(&clk->node);
-	up(&clocks_sem);
+	mutex_unlock(&clocks_mutex);
 }
 EXPORT_SYMBOL(clk_unregister);
 
diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c
index a1a900d..aab2729 100644
--- a/arch/arm/mach-pxa/corgi.c
+++ b/arch/arm/mach-pxa/corgi.c
@@ -44,6 +44,7 @@
 #include <asm/hardware/scoop.h>
 
 #include "generic.h"
+#include "devices.h"
 #include "sharpsl.h"
 
 
@@ -368,7 +369,7 @@
 	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.fixup		= fixup_corgi,
 	.map_io		= pxa_map_io,
-	.init_irq	= pxa_init_irq,
+	.init_irq	= pxa25x_init_irq,
 	.init_machine	= corgi_init,
 	.timer		= &pxa_timer,
 MACHINE_END
@@ -380,7 +381,7 @@
 	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.fixup		= fixup_corgi,
 	.map_io		= pxa_map_io,
-	.init_irq	= pxa_init_irq,
+	.init_irq	= pxa25x_init_irq,
 	.init_machine	= corgi_init,
 	.timer		= &pxa_timer,
 MACHINE_END
@@ -392,7 +393,7 @@
 	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.fixup		= fixup_corgi,
 	.map_io		= pxa_map_io,
-	.init_irq	= pxa_init_irq,
+	.init_irq	= pxa25x_init_irq,
 	.init_machine	= corgi_init,
 	.timer		= &pxa_timer,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/devices.h b/arch/arm/mach-pxa/devices.h
new file mode 100644
index 0000000..9a6faff
--- /dev/null
+++ b/arch/arm/mach-pxa/devices.h
@@ -0,0 +1,11 @@
+extern struct platform_device pxamci_device;
+extern struct platform_device pxaudc_device;
+extern struct platform_device pxafb_device;
+extern struct platform_device ffuart_device;
+extern struct platform_device btuart_device;
+extern struct platform_device stuart_device;
+extern struct platform_device hwuart_device;
+extern struct platform_device pxai2c_device;
+extern struct platform_device pxai2s_device;
+extern struct platform_device pxaficp_device;
+extern struct platform_device pxartc_device;
diff --git a/arch/arm/mach-pxa/dma.c b/arch/arm/mach-pxa/dma.c
index 4440bab..93c4f31 100644
--- a/arch/arm/mach-pxa/dma.c
+++ b/arch/arm/mach-pxa/dma.c
@@ -25,12 +25,15 @@
 
 #include <asm/arch/pxa-regs.h>
 
-static struct dma_channel {
+struct dma_channel {
 	char *name;
+	pxa_dma_prio prio;
 	void (*irq_handler)(int, void *);
 	void *data;
-} dma_channels[PXA_DMA_CHANNELS];
+};
 
+static struct dma_channel *dma_channels;
+static int num_dma_channels;
 
 int pxa_request_dma (char *name, pxa_dma_prio prio,
 			 void (*irq_handler)(int, void *),
@@ -47,8 +50,9 @@
 
 	do {
 		/* try grabbing a DMA channel with the requested priority */
-		pxa_for_each_dma_prio (i, prio) {
-			if (!dma_channels[i].name) {
+		for (i = 0; i < num_dma_channels; i++) {
+			if ((dma_channels[i].prio == prio) &&
+			    !dma_channels[i].name) {
 				found = 1;
 				break;
 			}
@@ -91,7 +95,7 @@
 {
 	int i, dint = DINT;
 
-	for (i = 0; i < PXA_DMA_CHANNELS; i++) {
+	for (i = 0; i < num_dma_channels; i++) {
 		if (dint & (1 << i)) {
 			struct dma_channel *channel = &dma_channels[i];
 			if (channel->name && channel->irq_handler) {
@@ -109,18 +113,32 @@
 	return IRQ_HANDLED;
 }
 
-static int __init pxa_dma_init (void)
+int __init pxa_init_dma(int num_ch)
 {
-	int ret;
+	int i, ret;
 
-	ret = request_irq (IRQ_DMA, dma_irq_handler, 0, "DMA", NULL);
-	if (ret)
+	dma_channels = kzalloc(sizeof(struct dma_channel) * num_ch, GFP_KERNEL);
+	if (dma_channels == NULL)
+		return -ENOMEM;
+
+	ret = request_irq(IRQ_DMA, dma_irq_handler, IRQF_DISABLED, "DMA", NULL);
+	if (ret) {
 		printk (KERN_CRIT "Wow!  Can't register IRQ for DMA\n");
-	return ret;
-}
+		kfree(dma_channels);
+		return ret;
+	}
 
-arch_initcall(pxa_dma_init);
+	/* dma channel priorities on pxa2xx processors:
+	 * ch 0 - 3,  16 - 19  <--> (0) DMA_PRIO_HIGH
+	 * ch 4 - 7,  20 - 23  <--> (1) DMA_PRIO_MEDIUM
+	 * ch 8 - 15, 24 - 31  <--> (2) DMA_PRIO_LOW
+	 */
+	for (i = 0; i < num_ch; i++)
+		dma_channels[i].prio = min((i & 0xf) >> 2, DMA_PRIO_LOW);
+
+	num_dma_channels = num_ch;
+	return 0;
+}
 
 EXPORT_SYMBOL(pxa_request_dma);
 EXPORT_SYMBOL(pxa_free_dma);
-
diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c
index 64b08b7..296539b 100644
--- a/arch/arm/mach-pxa/generic.c
+++ b/arch/arm/mach-pxa/generic.c
@@ -43,6 +43,7 @@
 #include <asm/arch/irda.h>
 #include <asm/arch/i2c.h>
 
+#include "devices.h"
 #include "generic.h"
 
 /*
@@ -242,7 +243,7 @@
 
 static u64 pxamci_dmamask = 0xffffffffUL;
 
-static struct platform_device pxamci_device = {
+struct platform_device pxamci_device = {
 	.name		= "pxa2xx-mci",
 	.id		= -1,
 	.dev		= {
@@ -281,7 +282,7 @@
 
 static u64 udc_dma_mask = ~(u32)0;
 
-static struct platform_device udc_device = {
+struct platform_device pxaudc_device = {
 	.name		= "pxa2xx-udc",
 	.id		= -1,
 	.resource	= pxa2xx_udc_resources,
@@ -307,7 +308,7 @@
 
 static u64 fb_dma_mask = ~(u64)0;
 
-static struct platform_device pxafb_device = {
+struct platform_device pxafb_device = {
 	.name		= "pxa2xx-fb",
 	.id		= -1,
 	.dev		= {
@@ -328,24 +329,24 @@
 	pxafb_device.dev.parent = parent_dev;
 }
 
-static struct platform_device ffuart_device = {
+struct platform_device ffuart_device = {
 	.name		= "pxa2xx-uart",
 	.id		= 0,
 };
-static struct platform_device btuart_device = {
+struct platform_device btuart_device = {
 	.name		= "pxa2xx-uart",
 	.id		= 1,
 };
-static struct platform_device stuart_device = {
+struct platform_device stuart_device = {
 	.name		= "pxa2xx-uart",
 	.id		= 2,
 };
-static struct platform_device hwuart_device = {
+struct platform_device hwuart_device = {
 	.name		= "pxa2xx-uart",
 	.id		= 3,
 };
 
-static struct resource i2c_resources[] = {
+static struct resource pxai2c_resources[] = {
 	{
 		.start	= 0x40301680,
 		.end	= 0x403016a3,
@@ -357,40 +358,19 @@
 	},
 };
 
-static struct platform_device i2c_device = {
+struct platform_device pxai2c_device = {
 	.name		= "pxa2xx-i2c",
 	.id		= 0,
-	.resource	= i2c_resources,
-	.num_resources	= ARRAY_SIZE(i2c_resources),
+	.resource	= pxai2c_resources,
+	.num_resources	= ARRAY_SIZE(pxai2c_resources),
 };
 
-#ifdef CONFIG_PXA27x
-static struct resource i2c_power_resources[] = {
-	{
-		.start	= 0x40f00180,
-		.end	= 0x40f001a3,
-		.flags	= IORESOURCE_MEM,
-	}, {
-		.start	= IRQ_PWRI2C,
-		.end	= IRQ_PWRI2C,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device i2c_power_device = {
-	.name		= "pxa2xx-i2c",
-	.id		= 1,
-	.resource	= i2c_power_resources,
-	.num_resources	= ARRAY_SIZE(i2c_resources),
-};
-#endif
-
 void __init pxa_set_i2c_info(struct i2c_pxa_platform_data *info)
 {
-	i2c_device.dev.platform_data = info;
+	pxai2c_device.dev.platform_data = info;
 }
 
-static struct resource i2s_resources[] = {
+static struct resource pxai2s_resources[] = {
 	{
 		.start	= 0x40400000,
 		.end	= 0x40400083,
@@ -402,16 +382,16 @@
 	},
 };
 
-static struct platform_device i2s_device = {
+struct platform_device pxai2s_device = {
 	.name		= "pxa2xx-i2s",
 	.id		= -1,
-	.resource	= i2s_resources,
-	.num_resources	= ARRAY_SIZE(i2s_resources),
+	.resource	= pxai2s_resources,
+	.num_resources	= ARRAY_SIZE(pxai2s_resources),
 };
 
 static u64 pxaficp_dmamask = ~(u32)0;
 
-static struct platform_device pxaficp_device = {
+struct platform_device pxaficp_device = {
 	.name		= "pxa2xx-ir",
 	.id		= -1,
 	.dev		= {
@@ -425,42 +405,7 @@
 	pxaficp_device.dev.platform_data = info;
 }
 
-static struct platform_device pxartc_device = {
+struct platform_device pxartc_device = {
 	.name		= "sa1100-rtc",
 	.id		= -1,
 };
-
-static struct platform_device *devices[] __initdata = {
-	&pxamci_device,
-	&udc_device,
-	&pxafb_device,
-	&ffuart_device,
-	&btuart_device,
-	&stuart_device,
-	&pxaficp_device,
-	&i2c_device,
-#ifdef CONFIG_PXA27x
-	&i2c_power_device,
-#endif
-	&i2s_device,
-	&pxartc_device,
-};
-
-static int __init pxa_init(void)
-{
-	int cpuid, ret;
-
-	ret = platform_add_devices(devices, ARRAY_SIZE(devices));
-	if (ret)
-		return ret;
-
-	/* Only add HWUART for PXA255/26x; PXA210/250/27x do not have it. */
-	cpuid = read_cpuid(CPUID_ID);
-	if (((cpuid >> 4) & 0xfff) == 0x2d0 ||
-	    ((cpuid >> 4) & 0xfff) == 0x290)
-		ret = platform_device_register(&hwuart_device);
-
-	return ret;
-}
-
-subsys_initcall(pxa_init);
diff --git a/arch/arm/mach-pxa/generic.h b/arch/arm/mach-pxa/generic.h
index e54a8dd..91ab2ad8 100644
--- a/arch/arm/mach-pxa/generic.h
+++ b/arch/arm/mach-pxa/generic.h
@@ -12,8 +12,12 @@
 struct sys_timer;
 
 extern struct sys_timer pxa_timer;
+extern void __init pxa_init_irq_low(void);
+extern void __init pxa_init_irq_high(void);
+extern void __init pxa_init_irq_gpio(int gpio_nr);
+extern void __init pxa25x_init_irq(void);
+extern void __init pxa27x_init_irq(void);
 extern void __init pxa_map_io(void);
-extern void __init pxa_init_irq(void);
 
 extern unsigned int get_clk_frequency_khz(int info);
 
diff --git a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c
index 64df440..465108d 100644
--- a/arch/arm/mach-pxa/idp.c
+++ b/arch/arm/mach-pxa/idp.c
@@ -38,6 +38,7 @@
 #include <asm/arch/mmc.h>
 
 #include "generic.h"
+#include "devices.h"
 
 /* TODO:
  * - add pxa2xx_audio_ops_t device structure
@@ -152,7 +153,7 @@
 static void __init idp_init_irq(void)
 {
 
-	pxa_init_irq();
+	pxa25x_init_irq();
 
 	set_irq_type(TOUCH_PANEL_IRQ, TOUCH_PANEL_IRQ_EDGE);
 }
diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c
index 4619d5f..4b867b0 100644
--- a/arch/arm/mach-pxa/irq.c
+++ b/arch/arm/mach-pxa/irq.c
@@ -30,12 +30,12 @@
 
 static void pxa_mask_low_irq(unsigned int irq)
 {
-	ICMR &= ~(1 << (irq + PXA_IRQ_SKIP));
+	ICMR &= ~(1 << irq);
 }
 
 static void pxa_unmask_low_irq(unsigned int irq)
 {
-	ICMR |= (1 << (irq + PXA_IRQ_SKIP));
+	ICMR |= (1 << irq);
 }
 
 static int pxa_set_wake(unsigned int irq, unsigned int on)
@@ -67,7 +67,27 @@
 	.set_wake	= pxa_set_wake,
 };
 
-#if PXA_INTERNAL_IRQS > 32
+void __init pxa_init_irq_low(void)
+{
+	int irq;
+
+	/* disable all IRQs */
+	ICMR = 0;
+
+	/* all IRQs are IRQ, not FIQ */
+	ICLR = 0;
+
+	/* only unmasked interrupts kick us out of idle */
+	ICCR = 1;
+
+	for (irq = PXA_IRQ(0); irq <= PXA_IRQ(31); irq++) {
+		set_irq_chip(irq, &pxa_internal_chip_low);
+		set_irq_handler(irq, handle_level_irq);
+		set_irq_flags(irq, IRQF_VALID);
+	}
+}
+
+#ifdef CONFIG_PXA27x
 
 /*
  * This is for the second set of internal IRQs as found on the PXA27x.
@@ -75,12 +95,12 @@
 
 static void pxa_mask_high_irq(unsigned int irq)
 {
-	ICMR2 &= ~(1 << (irq - 32 + PXA_IRQ_SKIP));
+	ICMR2 &= ~(1 << (irq - 32));
 }
 
 static void pxa_unmask_high_irq(unsigned int irq)
 {
-	ICMR2 |= (1 << (irq - 32 + PXA_IRQ_SKIP));
+	ICMR2 |= (1 << (irq - 32));
 }
 
 static struct irq_chip pxa_internal_chip_high = {
@@ -90,6 +110,19 @@
 	.unmask		= pxa_unmask_high_irq,
 };
 
+void __init pxa_init_irq_high(void)
+{
+	int irq;
+
+	ICMR2 = 0;
+	ICLR2 = 0;
+
+	for (irq = PXA_IRQ(32); irq < PXA_IRQ(64); irq++) {
+		set_irq_chip(irq, &pxa_internal_chip_high);
+		set_irq_handler(irq, handle_level_irq);
+		set_irq_flags(irq, IRQF_VALID);
+	}
+}
 #endif
 
 /* Note that if an input/irq line ever gets changed to an output during
@@ -217,7 +250,7 @@
 	do {
 		loop = 0;
 
-		mask = GEDR0 & ~3;
+		mask = GEDR0 & GPIO_IRQ_mask[0] & ~3;
 		if (mask) {
 			GEDR0 = mask;
 			irq = IRQ_GPIO(2);
@@ -233,7 +266,7 @@
 			loop = 1;
 		}
 
-		mask = GEDR1;
+		mask = GEDR1 & GPIO_IRQ_mask[1];
 		if (mask) {
 			GEDR1 = mask;
 			irq = IRQ_GPIO(32);
@@ -248,7 +281,7 @@
 			loop = 1;
 		}
 
-		mask = GEDR2;
+		mask = GEDR2 & GPIO_IRQ_mask[2];
 		if (mask) {
 			GEDR2 = mask;
 			irq = IRQ_GPIO(64);
@@ -263,8 +296,7 @@
 			loop = 1;
 		}
 
-#if PXA_LAST_GPIO >= 96
-		mask = GEDR3;
+		mask = GEDR3 & GPIO_IRQ_mask[3];
 		if (mask) {
 			GEDR3 = mask;
 			irq = IRQ_GPIO(96);
@@ -278,7 +310,6 @@
 			} while (mask);
 			loop = 1;
 		}
-#endif
 	} while (loop);
 }
 
@@ -314,64 +345,27 @@
 	.set_wake	= pxa_set_gpio_wake,
 };
 
-
-void __init pxa_init_irq(void)
+void __init pxa_init_irq_gpio(int gpio_nr)
 {
-	int irq;
-
-	/* disable all IRQs */
-	ICMR = 0;
-
-	/* all IRQs are IRQ, not FIQ */
-	ICLR = 0;
+	int irq, i;
 
 	/* clear all GPIO edge detects */
-	GFER0 = 0;
-	GFER1 = 0;
-	GFER2 = 0;
-	GRER0 = 0;
-	GRER1 = 0;
-	GRER2 = 0;
-	GEDR0 = GEDR0;
-	GEDR1 = GEDR1;
-	GEDR2 = GEDR2;
-
-#ifdef CONFIG_PXA27x
-	/* And similarly for the extra regs on the PXA27x */
-	ICMR2 = 0;
-	ICLR2 = 0;
-	GFER3 = 0;
-	GRER3 = 0;
-	GEDR3 = GEDR3;
-#endif
-
-	/* only unmasked interrupts kick us out of idle */
-	ICCR = 1;
+	for (i = 0; i < gpio_nr; i += 32) {
+		GFER(i) = 0;
+		GRER(i) = 0;
+		GEDR(i) = GEDR(i);
+	}
 
 	/* GPIO 0 and 1 must have their mask bit always set */
 	GPIO_IRQ_mask[0] = 3;
 
-	for (irq = PXA_IRQ(PXA_IRQ_SKIP); irq <= PXA_IRQ(31); irq++) {
-		set_irq_chip(irq, &pxa_internal_chip_low);
-		set_irq_handler(irq, handle_level_irq);
-		set_irq_flags(irq, IRQF_VALID);
-	}
-
-#if PXA_INTERNAL_IRQS > 32
-	for (irq = PXA_IRQ(32); irq < PXA_IRQ(PXA_INTERNAL_IRQS); irq++) {
-		set_irq_chip(irq, &pxa_internal_chip_high);
-		set_irq_handler(irq, handle_level_irq);
-		set_irq_flags(irq, IRQF_VALID);
-	}
-#endif
-
 	for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) {
 		set_irq_chip(irq, &pxa_low_gpio_chip);
 		set_irq_handler(irq, handle_edge_irq);
 		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 	}
 
-	for (irq = IRQ_GPIO(2); irq <= IRQ_GPIO(PXA_LAST_GPIO); irq++) {
+	for (irq = IRQ_GPIO(2); irq <= IRQ_GPIO(gpio_nr); irq++) {
 		set_irq_chip(irq, &pxa_muxed_gpio_chip);
 		set_irq_handler(irq, handle_edge_irq);
 		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
diff --git a/arch/arm/mach-pxa/lpd270.c b/arch/arm/mach-pxa/lpd270.c
index e309766..2611644 100644
--- a/arch/arm/mach-pxa/lpd270.c
+++ b/arch/arm/mach-pxa/lpd270.c
@@ -46,6 +46,7 @@
 #include <asm/arch/ohci.h>
 
 #include "generic.h"
+#include "devices.h"
 
 
 static unsigned int lpd270_irq_enabled;
@@ -97,7 +98,7 @@
 {
 	int irq;
 
-	pxa_init_irq();
+	pxa27x_init_irq();
 
 	__raw_writew(0, LPD270_INT_MASK);
 	__raw_writew(0, LPD270_INT_STATUS);
diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
index 6377b2e..e70048f 100644
--- a/arch/arm/mach-pxa/lubbock.c
+++ b/arch/arm/mach-pxa/lubbock.c
@@ -48,6 +48,7 @@
 #include <asm/arch/mmc.h>
 
 #include "generic.h"
+#include "devices.h"
 
 
 #define LUB_MISC_WR		__LUB_REG(LUBBOCK_FPGA_PHYS + 0x080)
@@ -103,7 +104,7 @@
 {
 	int irq;
 
-	pxa_init_irq();
+	pxa25x_init_irq();
 
 	/* setup extra lubbock irqs */
 	for (irq = LUBBOCK_IRQ(0); irq <= LUBBOCK_LAST_IRQ; irq++) {
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
index ed99a81..b02c79c 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -46,6 +46,7 @@
 #include <asm/arch/ohci.h>
 
 #include "generic.h"
+#include "devices.h"
 
 
 static unsigned long mainstone_irq_enabled;
@@ -89,7 +90,7 @@
 {
 	int irq;
 
-	pxa_init_irq();
+	pxa27x_init_irq();
 
 	/* setup extra Mainstone irqs */
 	for(irq = MAINSTONE_IRQ(0); irq <= MAINSTONE_IRQ(15); irq++) {
diff --git a/arch/arm/mach-pxa/pm.c b/arch/arm/mach-pxa/pm.c
index 6bf15ae..e66dbc2 100644
--- a/arch/arm/mach-pxa/pm.c
+++ b/arch/arm/mach-pxa/pm.c
@@ -77,7 +77,6 @@
 {
 	unsigned long sleep_save[SLEEP_SAVE_SIZE];
 	unsigned long checksum = 0;
-	struct timespec delta, rtc;
 	int i;
 	extern void pxa_cpu_pm_enter(suspend_state_t state);
 
@@ -87,11 +86,6 @@
 		iwmmxt_task_disable(NULL);
 #endif
 
-	/* preserve current time */
-	rtc.tv_sec = RCNR;
-	rtc.tv_nsec = 0;
-	save_time_delta(&delta, &rtc);
-
 	SAVE(GPLR0); SAVE(GPLR1); SAVE(GPLR2);
 	SAVE(GPDR0); SAVE(GPDR1); SAVE(GPDR2);
 	SAVE(GRER0); SAVE(GRER1); SAVE(GRER2);
@@ -183,10 +177,6 @@
 
 	RESTORE(PSTR);
 
-	/* restore current time */
-	rtc.tv_sec = RCNR;
-	restore_time_delta(&delta, &rtc);
-
 #ifdef DEBUG
 	printk(KERN_DEBUG "*** made it back from resume\n");
 #endif
@@ -200,40 +190,3 @@
 {
 	return virt_to_phys(sp);
 }
-
-/*
- * Called after processes are frozen, but before we shut down devices.
- */
-int pxa_pm_prepare(suspend_state_t state)
-{
-	extern int pxa_cpu_pm_prepare(suspend_state_t state);
-
-	return pxa_cpu_pm_prepare(state);
-}
-
-EXPORT_SYMBOL_GPL(pxa_pm_prepare);
-
-/*
- * Called after devices are re-setup, but before processes are thawed.
- */
-int pxa_pm_finish(suspend_state_t state)
-{
-	return 0;
-}
-
-EXPORT_SYMBOL_GPL(pxa_pm_finish);
-
-static struct pm_ops pxa_pm_ops = {
-	.prepare	= pxa_pm_prepare,
-	.enter		= pxa_pm_enter,
-	.finish		= pxa_pm_finish,
-	.valid		= pm_valid_only_mem,
-};
-
-static int __init pxa_pm_init(void)
-{
-	pm_set_ops(&pxa_pm_ops);
-	return 0;
-}
-
-device_initcall(pxa_pm_init);
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
index 34fb80b..655668d 100644
--- a/arch/arm/mach-pxa/poodle.c
+++ b/arch/arm/mach-pxa/poodle.c
@@ -45,6 +45,7 @@
 #include <asm/mach/sharpsl_param.h>
 
 #include "generic.h"
+#include "devices.h"
 #include "sharpsl.h"
 
 static struct resource poodle_scoop_resources[] = {
@@ -412,7 +413,7 @@
 	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.fixup		= fixup_poodle,
 	.map_io		= pxa_map_io,
-	.init_irq	= pxa_init_irq,
+	.init_irq	= pxa25x_init_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= poodle_init,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index c1f2173..f36ca44 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -19,12 +19,17 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/platform_device.h>
 #include <linux/pm.h>
 
 #include <asm/hardware.h>
+#include <asm/arch/irqs.h>
 #include <asm/arch/pxa-regs.h>
+#include <asm/arch/pm.h>
+#include <asm/arch/dma.h>
 
 #include "generic.h"
+#include "devices.h"
 
 /*
  * Various clock factors driven by the CCCR register.
@@ -105,18 +110,6 @@
 
 #ifdef CONFIG_PM
 
-int pxa_cpu_pm_prepare(suspend_state_t state)
-{
-	switch (state) {
-	case PM_SUSPEND_MEM:
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
 void pxa_cpu_pm_enter(suspend_state_t state)
 {
 	extern void pxa_cpu_suspend(unsigned int);
@@ -133,4 +126,49 @@
 	}
 }
 
+static struct pm_ops pxa25x_pm_ops = {
+	.enter		= pxa_pm_enter,
+	.valid		= pm_valid_only_mem,
+};
 #endif
+
+void __init pxa25x_init_irq(void)
+{
+	pxa_init_irq_low();
+	pxa_init_irq_gpio(85);
+}
+
+static struct platform_device *pxa25x_devices[] __initdata = {
+	&pxamci_device,
+	&pxaudc_device,
+	&pxafb_device,
+	&ffuart_device,
+	&btuart_device,
+	&stuart_device,
+	&pxai2c_device,
+	&pxai2s_device,
+	&pxaficp_device,
+	&pxartc_device,
+};
+
+static int __init pxa25x_init(void)
+{
+	int ret = 0;
+
+	if (cpu_is_pxa21x() || cpu_is_pxa25x()) {
+		if ((ret = pxa_init_dma(16)))
+			return ret;
+#ifdef CONFIG_PM
+		pm_set_ops(&pxa25x_pm_ops);
+#endif
+		ret = platform_add_devices(pxa25x_devices,
+					   ARRAY_SIZE(pxa25x_devices));
+	}
+	/* Only add HWUART for PXA255/26x; PXA210/250/27x do not have it. */
+	if (cpu_is_pxa25x())
+		ret = platform_device_register(&hwuart_device);
+
+	return ret;
+}
+
+subsys_initcall(pxa25x_init);
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index 1939acc..aa5bb02 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -19,10 +19,14 @@
 
 #include <asm/hardware.h>
 #include <asm/irq.h>
+#include <asm/arch/irqs.h>
 #include <asm/arch/pxa-regs.h>
 #include <asm/arch/ohci.h>
+#include <asm/arch/pm.h>
+#include <asm/arch/dma.h>
 
 #include "generic.h"
+#include "devices.h"
 
 /* Crystal clock: 13MHz */
 #define BASE_CLK	13000000
@@ -122,17 +126,6 @@
 
 #ifdef CONFIG_PM
 
-int pxa_cpu_pm_prepare(suspend_state_t state)
-{
-	switch (state) {
-	case PM_SUSPEND_MEM:
-	case PM_SUSPEND_STANDBY:
-		return 0;
-	default:
-		return -EINVAL;
-	}
-}
-
 void pxa_cpu_pm_enter(suspend_state_t state)
 {
 	extern void pxa_cpu_standby(void);
@@ -162,6 +155,15 @@
 	}
 }
 
+static int pxa27x_pm_valid(suspend_state_t state)
+{
+	return state == PM_SUSPEND_MEM || state == PM_SUSPEND_STANDBY;
+}
+
+static struct pm_ops pxa27x_pm_ops = {
+	.enter		= pxa_pm_enter,
+	.valid		= pxa27x_pm_valid,
+};
 #endif
 
 /*
@@ -183,7 +185,7 @@
 	},
 };
 
-static struct platform_device ohci_device = {
+static struct platform_device pxaohci_device = {
 	.name		= "pxa27x-ohci",
 	.id		= -1,
 	.dev		= {
@@ -196,16 +198,62 @@
 
 void __init pxa_set_ohci_info(struct pxaohci_platform_data *info)
 {
-	ohci_device.dev.platform_data = info;
+	pxaohci_device.dev.platform_data = info;
 }
 
-static struct platform_device *devices[] __initdata = {
-	&ohci_device,
+static struct resource i2c_power_resources[] = {
+	{
+		.start	= 0x40f00180,
+		.end	= 0x40f001a3,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= IRQ_PWRI2C,
+		.end	= IRQ_PWRI2C,
+		.flags	= IORESOURCE_IRQ,
+	},
 };
 
+static struct platform_device pxai2c_power_device = {
+	.name		= "pxa2xx-i2c",
+	.id		= 1,
+	.resource	= i2c_power_resources,
+	.num_resources	= ARRAY_SIZE(i2c_power_resources),
+};
+
+static struct platform_device *devices[] __initdata = {
+	&pxamci_device,
+	&pxaudc_device,
+	&pxafb_device,
+	&ffuart_device,
+	&btuart_device,
+	&stuart_device,
+	&pxai2c_device,
+	&pxai2c_power_device,
+	&pxai2s_device,
+	&pxaficp_device,
+	&pxartc_device,
+	&pxaohci_device,
+};
+
+void __init pxa27x_init_irq(void)
+{
+	pxa_init_irq_low();
+	pxa_init_irq_high();
+	pxa_init_irq_gpio(128);
+}
+
 static int __init pxa27x_init(void)
 {
-	return platform_add_devices(devices, ARRAY_SIZE(devices));
+	int ret = 0;
+	if (cpu_is_pxa27x()) {
+		if ((ret = pxa_init_dma(32)))
+			return ret;
+#ifdef CONFIG_PM
+		pm_set_ops(&pxa27x_pm_ops);
+#endif
+		ret = platform_add_devices(devices, ARRAY_SIZE(devices));
+	}
+	return ret;
 }
 
 subsys_initcall(pxa27x_init);
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index 3cbac63..bae47e1 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -48,6 +48,7 @@
 #include <asm/hardware/scoop.h>
 
 #include "generic.h"
+#include "devices.h"
 #include "sharpsl.h"
 
 /*
@@ -560,7 +561,7 @@
 	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.fixup		= fixup_spitz,
 	.map_io		= pxa_map_io,
-	.init_irq	= pxa_init_irq,
+	.init_irq	= pxa27x_init_irq,
 	.init_machine	= spitz_init,
 	.timer		= &pxa_timer,
 MACHINE_END
@@ -572,7 +573,7 @@
 	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.fixup		= fixup_spitz,
 	.map_io		= pxa_map_io,
-	.init_irq	= pxa_init_irq,
+	.init_irq	= pxa27x_init_irq,
 	.init_machine	= spitz_init,
 	.timer		= &pxa_timer,
 MACHINE_END
@@ -584,7 +585,7 @@
 	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.fixup		= fixup_spitz,
 	.map_io		= pxa_map_io,
-	.init_irq	= pxa_init_irq,
+	.init_irq	= pxa27x_init_irq,
 	.init_machine	= akita_init,
 	.timer		= &pxa_timer,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c
index 5248abe..6f91fd2 100644
--- a/arch/arm/mach-pxa/time.c
+++ b/arch/arm/mach-pxa/time.c
@@ -30,11 +30,6 @@
 #include <asm/arch/pxa-regs.h>
 
 
-static inline unsigned long pxa_get_rtc_time(void)
-{
-	return RCNR;
-}
-
 static int pxa_set_rtc(void)
 {
 	unsigned long current_time = xtime.tv_sec;
@@ -122,10 +117,6 @@
 
 	set_rtc = pxa_set_rtc;
 
-	tv.tv_nsec = 0;
-	tv.tv_sec = pxa_get_rtc_time();
-	do_settimeofday(&tv);
-
 	OIER = 0;		/* disable any timer interrupts */
 	OSSR = 0xf;		/* clear status on all timers */
 	setup_irq(IRQ_OST0, &pxa_timer_irq);
diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c
index 7273877..240fd04 100644
--- a/arch/arm/mach-pxa/tosa.c
+++ b/arch/arm/mach-pxa/tosa.c
@@ -42,7 +42,7 @@
 #include <asm/mach/sharpsl_param.h>
 
 #include "generic.h"
-
+#include "devices.h"
 
 /*
  * SCOOP Device
@@ -332,7 +332,7 @@
 	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.fixup          = fixup_tosa,
 	.map_io         = pxa_map_io,
-	.init_irq       = pxa_init_irq,
+	.init_irq       = pxa25x_init_irq,
 	.init_machine   = tosa_init,
 	.timer          = &pxa_timer,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/trizeps4.c b/arch/arm/mach-pxa/trizeps4.c
index 28c79bd..e4ba43b 100644
--- a/arch/arm/mach-pxa/trizeps4.c
+++ b/arch/arm/mach-pxa/trizeps4.c
@@ -49,6 +49,7 @@
 #include <asm/arch/ohci.h>
 
 #include "generic.h"
+#include "devices.h"
 
 /********************************************************************************************
  * ONBOARD FLASH
@@ -503,7 +504,7 @@
 	.boot_params	= TRIZEPS4_SDRAM_BASE + 0x100,
 	.init_machine	= trizeps4_init,
 	.map_io		= trizeps4_map_io,
-	.init_irq	= pxa_init_irq,
+	.init_irq	= pxa27x_init_irq,
 	.timer		= &pxa_timer,
 MACHINE_END
 
diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c
index f01de80..8b52ea9 100644
--- a/arch/arm/mach-s3c2410/mach-bast.c
+++ b/arch/arm/mach-s3c2410/mach-bast.c
@@ -20,6 +20,8 @@
 #include <linux/platform_device.h>
 #include <linux/dm9000.h>
 
+#include <net/ax88796.h>
+
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
@@ -409,6 +411,61 @@
 	.max_freq	= 130*1000,
 };
 
+/* Asix AX88796 10/100 ethernet controller */
+
+static struct ax_plat_data bast_asix_platdata = {
+	.flags		= AXFLG_MAC_FROMDEV,
+	.wordlength	= 2,
+	.dcr_val	= 0x48,
+	.rcr_val	= 0x40,
+};
+
+static struct resource bast_asix_resource[] = {
+	[0] = {
+		.start = S3C2410_CS5 + BAST_PA_ASIXNET,
+		.end   = S3C2410_CS5 + BAST_PA_ASIXNET + (0x18 * 0x20) - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = S3C2410_CS5 + BAST_PA_ASIXNET + (0x1f * 0x20),
+		.end   = S3C2410_CS5 + BAST_PA_ASIXNET + (0x1f * 0x20),
+		.flags = IORESOURCE_MEM,
+	},
+	[2] = {
+		.start = IRQ_ASIX,
+		.end   = IRQ_ASIX,
+		.flags = IORESOURCE_IRQ
+	}
+};
+
+static struct platform_device bast_device_asix = {
+	.name		= "ax88796",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(bast_asix_resource),
+	.resource	= bast_asix_resource,
+	.dev		= {
+		.platform_data = &bast_asix_platdata
+	}
+};
+
+/* Asix AX88796 10/100 ethernet controller parallel port */
+
+static struct resource bast_asixpp_resource[] = {
+	[0] = {
+		.start = S3C2410_CS5 + BAST_PA_ASIXNET + (0x18 * 0x20),
+		.end   = S3C2410_CS5 + BAST_PA_ASIXNET + (0x1b * 0x20) - 1,
+		.flags = IORESOURCE_MEM,
+	}
+};
+
+static struct platform_device bast_device_axpp = {
+	.name		= "ax88796-pp",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(bast_asixpp_resource),
+	.resource	= bast_asixpp_resource,
+};
+
+/* LCD/VGA controller */
 
 static struct s3c2410fb_mach_info __initdata bast_lcd_info = {
 	.width		= 640,
@@ -453,6 +510,8 @@
 	&s3c_device_nand,
 	&bast_device_nor,
 	&bast_device_dm9k,
+	&bast_device_asix,
+	&bast_device_axpp,
 	&bast_sio,
 };
 
diff --git a/arch/arm/mach-s3c2440/mach-anubis.c b/arch/arm/mach-s3c2440/mach-anubis.c
index bff7ddd..29c163d 100644
--- a/arch/arm/mach-s3c2440/mach-anubis.c
+++ b/arch/arm/mach-s3c2440/mach-anubis.c
@@ -18,6 +18,9 @@
 #include <linux/serial_core.h>
 #include <linux/platform_device.h>
 
+#include <linux/sm501.h>
+#include <linux/sm501-regs.h>
+
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
@@ -42,6 +45,8 @@
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/partitions.h>
 
+#include <net/ax88796.h>
+
 #include <asm/plat-s3c24xx/clock.h>
 #include <asm/plat-s3c24xx/devs.h>
 #include <asm/plat-s3c24xx/cpu.h>
@@ -153,6 +158,29 @@
 	}
 };
 
+static struct mtd_partition anubis_default_nand_part_large[] = {
+	[0] = {
+		.name	= "Boot Agent",
+		.size	= SZ_128K,
+		.offset	= 0,
+	},
+	[1] = {
+		.name	= "/boot",
+		.size	= SZ_4M - SZ_128K,
+		.offset	= SZ_128K,
+	},
+	[2] = {
+		.name	= "user1",
+		.offset	= SZ_4M,
+		.size	= SZ_32M - SZ_4M,
+	},
+	[3] = {
+		.name	= "user2",
+		.offset	= SZ_32M,
+		.size	= MTDPART_SIZ_FULL,
+	}
+};
+
 /* the Anubis has 3 selectable slots for nand-flash, the two
  * on-board chip areas, as well as the external slot.
  *
@@ -260,6 +288,104 @@
 	.resource	= anubis_ide1_resource,
 };
 
+/* Asix AX88796 10/100 ethernet controller */
+
+static struct ax_plat_data anubis_asix_platdata = {
+	.flags		= AXFLG_MAC_FROMDEV,
+	.wordlength	= 2,
+	.dcr_val	= 0x48,
+	.rcr_val	= 0x40,
+};
+
+static struct resource anubis_asix_resource[] = {
+	[0] = {
+		.start = S3C2410_CS5,
+		.end   = S3C2410_CS5 + (0x20 * 0x20) -1,
+		.flags = IORESOURCE_MEM
+	},
+	[1] = {
+		.start = IRQ_ASIX,
+		.end   = IRQ_ASIX,
+		.flags = IORESOURCE_IRQ
+	}
+};
+
+static struct platform_device anubis_device_asix = {
+	.name		= "ax88796",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(anubis_asix_resource),
+	.resource	= anubis_asix_resource,
+	.dev		= {
+		.platform_data = &anubis_asix_platdata,
+	}
+};
+
+/* SM501 */
+
+static struct resource anubis_sm501_resource[] = {
+	[0] = {
+		.start	= S3C2410_CS2,
+		.end	= S3C2410_CS2 + SZ_8M,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= S3C2410_CS2 + SZ_64M - SZ_2M,
+		.end	= S3C2410_CS2 + SZ_64M - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[2] = {
+		.start	= IRQ_EINT0,
+		.end	= IRQ_EINT0,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct sm501_initdata anubis_sm501_initdata = {
+	.gpio_high	= {
+		.set	= 0x3F000000,		/* 24bit panel */
+		.mask	= 0x0,
+	},
+	.misc_timing	= {
+		.set	= 0x010100,		/* SDRAM timing */
+		.mask	= 0x1F1F00,
+	},
+	.misc_control	= {
+		.set	= SM501_MISC_PNL_24BIT,
+		.mask	= 0,
+	},
+
+	/* set the SDRAM and bus clocks */
+	.mclk		= 72 * MHZ,
+	.m1xclk		= 144 * MHZ,
+};
+
+static struct sm501_platdata_gpio_i2c anubis_sm501_gpio_i2c[] = {
+	[0] = {
+		.pin_scl	= 44,
+		.pin_sda	= 45,
+	},
+	[1] = {
+		.pin_scl	= 40,
+		.pin_sda	= 41,
+	},
+};
+
+static struct sm501_platdata anubis_sm501_platdata = {
+	.init		= &anubis_sm501_initdata,
+	.gpio_i2c	= anubis_sm501_gpio_i2c,
+	.gpio_i2c_nr	= ARRAY_SIZE(anubis_sm501_gpio_i2c),
+};
+
+static struct platform_device anubis_device_sm501 = {
+	.name		= "sm501",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(anubis_sm501_resource),
+	.resource	= anubis_sm501_resource,
+	.dev		= {
+		.platform_data = &anubis_sm501_platdata,
+	},
+};
+
 /* Standard Anubis devices */
 
 static struct platform_device *anubis_devices[] __initdata = {
@@ -271,6 +397,8 @@
 	&s3c_device_nand,
 	&anubis_device_ide0,
 	&anubis_device_ide1,
+	&anubis_device_asix,
+	&anubis_device_sm501,
 };
 
 static struct clk *anubis_clocks[] = {
@@ -304,8 +432,17 @@
 	s3c24xx_init_clocks(0);
 	s3c24xx_init_uarts(anubis_uartcfgs, ARRAY_SIZE(anubis_uartcfgs));
 
-	/* ensure that the GPIO is setup */
-	s3c2410_gpio_setpin(S3C2410_GPA0, 1);
+	/* check for the newer revision boards with large page nand */
+
+	if ((__raw_readb(ANUBIS_VA_IDREG) & ANUBIS_IDREG_REVMASK) >= 4) {
+		printk(KERN_INFO "ANUBIS-B detected (revision %d)\n",
+		       __raw_readb(ANUBIS_VA_IDREG) & ANUBIS_IDREG_REVMASK);
+		anubis_nand_sets[0].partitions = anubis_default_nand_part_large;
+		anubis_nand_sets[0].nr_partitions = ARRAY_SIZE(anubis_default_nand_part_large);
+	} else {
+		/* ensure that the GPIO is setup */
+		s3c2410_gpio_setpin(S3C2410_GPA0, 1);
+	}
 }
 
 static void __init anubis_init(void)
diff --git a/arch/arm/mach-s3c2440/mach-osiris.c b/arch/arm/mach-s3c2440/mach-osiris.c
index 1581160..89f4c9c 100644
--- a/arch/arm/mach-s3c2440/mach-osiris.c
+++ b/arch/arm/mach-s3c2440/mach-osiris.c
@@ -166,6 +166,29 @@
 	}
 };
 
+static struct mtd_partition osiris_default_nand_part_large[] = {
+	[0] = {
+		.name	= "Boot Agent",
+		.size	= SZ_128K,
+		.offset	= 0,
+	},
+	[1] = {
+		.name	= "/boot",
+		.size	= SZ_4M - SZ_128K,
+		.offset	= SZ_128K,
+	},
+	[2] = {
+		.name	= "user1",
+		.offset	= SZ_4M,
+		.size	= SZ_32M - SZ_4M,
+	},
+	[3] = {
+		.name	= "user2",
+		.offset	= SZ_32M,
+		.size	= MTDPART_SIZ_FULL,
+	}
+};
+
 /* the Osiris has 3 selectable slots for nand-flash, the two
  * on-board chip areas, as well as the external slot.
  *
@@ -322,14 +345,23 @@
 	s3c24xx_init_clocks(0);
 	s3c24xx_init_uarts(osiris_uartcfgs, ARRAY_SIZE(osiris_uartcfgs));
 
+	/* check for the newer revision boards with large page nand */
+
+	if ((__raw_readb(OSIRIS_VA_IDREG) & OSIRIS_ID_REVMASK) >= 4) {
+		printk(KERN_INFO "OSIRIS-B detected (revision %d)\n",
+		       __raw_readb(OSIRIS_VA_IDREG) & OSIRIS_ID_REVMASK);
+		osiris_nand_sets[0].partitions = osiris_default_nand_part_large;
+		osiris_nand_sets[0].nr_partitions = ARRAY_SIZE(osiris_default_nand_part_large);
+	} else {
+		/* write-protect line to the NAND */
+		s3c2410_gpio_setpin(S3C2410_GPA0, 1);
+	}
+
 	/* fix bus configuration (nBE settings wrong on ABLE pre v2.20) */
 
 	local_irq_save(flags);
 	__raw_writel(__raw_readl(S3C2410_BWSCON) | S3C2410_BWSCON_ST1 | S3C2410_BWSCON_ST2 | S3C2410_BWSCON_ST3 | S3C2410_BWSCON_ST4 | S3C2410_BWSCON_ST5, S3C2410_BWSCON);
 	local_irq_restore(flags);
-
-	/* write-protect line to the NAND */
-	s3c2410_gpio_setpin(S3C2410_GPA0, 1);
 }
 
 static void __init osiris_init(void)
diff --git a/arch/arm/mach-sa1100/pm.c b/arch/arm/mach-sa1100/pm.c
index d674cf3..01a37d3 100644
--- a/arch/arm/mach-sa1100/pm.c
+++ b/arch/arm/mach-sa1100/pm.c
@@ -57,12 +57,7 @@
 static int sa11x0_pm_enter(suspend_state_t state)
 {
 	unsigned long gpio, sleep_save[SLEEP_SAVE_SIZE];
-	struct timespec delta, rtc;
 
-	/* preserve current time */
-	rtc.tv_sec = RCNR;
-	rtc.tv_nsec = 0;
-	save_time_delta(&delta, &rtc);
 	gpio = GPLR;
 
 	/* save vital registers */
@@ -119,10 +114,6 @@
 	 */
 	PSSR = PSSR_PH;
 
-	/* restore current time */
-	rtc.tv_sec = RCNR;
-	restore_time_delta(&delta, &rtc);
-
 	return 0;
 }
 
diff --git a/arch/arm/mach-sa1100/time.c b/arch/arm/mach-sa1100/time.c
index 29cb0c1..fdf7b01 100644
--- a/arch/arm/mach-sa1100/time.c
+++ b/arch/arm/mach-sa1100/time.c
@@ -21,25 +21,6 @@
 #define RTC_DEF_DIVIDER		(32768 - 1)
 #define RTC_DEF_TRIM            0
 
-static unsigned long __init sa1100_get_rtc_time(void)
-{
-	/*
-	 * According to the manual we should be able to let RTTR be zero
-	 * and then a default divisor for a 32.768KHz clock is used.
-	 * Apparently this doesn't work, at least for my SA1110 rev 5.
-	 * If the clock divider is uninitialized then reset it to the
-	 * default value to get the 1Hz clock.
-	 */
-	if (RTTR == 0) {
-		RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16);
-		printk(KERN_WARNING "Warning: uninitialized Real Time Clock\n");
-		/* The current RTC value probably doesn't make sense either */
-		RCNR = 0;
-		return 0;
-	}
-	return RCNR;
-}
-
 static int sa1100_set_rtc(void)
 {
 	unsigned long current_time = xtime.tv_sec;
@@ -117,15 +98,10 @@
 
 static void __init sa1100_timer_init(void)
 {
-	struct timespec tv;
 	unsigned long flags;
 
 	set_rtc = sa1100_set_rtc;
 
-	tv.tv_nsec = 0;
-	tv.tv_sec = sa1100_get_rtc_time();
-	do_settimeofday(&tv);
-
 	OIER = 0;		/* disable any timer interrupts */
 	OSSR = 0xf;		/* clear status on all timers */
 	setup_irq(IRQ_OST0, &sa1100_timer_irq);
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
index f3ade18..7595277 100644
--- a/arch/arm/mm/ioremap.c
+++ b/arch/arm/mm/ioremap.c
@@ -280,7 +280,10 @@
 	if (!type)
 		return NULL;
 
-	size = PAGE_ALIGN(size);
+	/*
+	 * Page align the mapping size, taking account of any offset.
+	 */
+	size = PAGE_ALIGN(offset + size);
 
  	area = get_vm_area(size, VM_IOREMAP);
  	if (!area)
@@ -325,11 +328,6 @@
 	if (!size || last_addr < phys_addr)
 		return NULL;
 
-	/*
- 	 * Page align the mapping size
-	 */
-	size = PAGE_ALIGN(last_addr + 1) - phys_addr;
-
  	return __arm_ioremap_pfn(pfn, offset, size, mtype);
 }
 EXPORT_SYMBOL(__arm_ioremap);
diff --git a/drivers/mmc/host/pxamci.h b/drivers/mmc/host/pxamci.h
index 1b16322..df17c28 100644
--- a/drivers/mmc/host/pxamci.h
+++ b/drivers/mmc/host/pxamci.h
@@ -1,25 +1,3 @@
-#undef MMC_STRPCL
-#undef MMC_STAT
-#undef MMC_CLKRT
-#undef MMC_SPI
-#undef MMC_CMDAT
-#undef MMC_RESTO
-#undef MMC_RDTO
-#undef MMC_BLKLEN
-#undef MMC_NOB
-#undef MMC_PRTBUF
-#undef MMC_I_MASK
-#undef END_CMD_RES
-#undef PRG_DONE
-#undef DATA_TRAN_DONE
-#undef MMC_I_REG
-#undef MMC_CMD
-#undef MMC_ARGH
-#undef MMC_ARGL
-#undef MMC_RES
-#undef MMC_RXFIFO
-#undef MMC_TXFIFO
-
 #define MMC_STRPCL	0x0000
 #define STOP_CLOCK		(1 << 0)
 #define START_CLOCK		(2 << 0)
diff --git a/include/asm-arm/Kbuild b/include/asm-arm/Kbuild
index c68e168..73237bd 100644
--- a/include/asm-arm/Kbuild
+++ b/include/asm-arm/Kbuild
@@ -1 +1,3 @@
 include include/asm-generic/Kbuild.asm
+
+unifdef-y += hwcap.h
diff --git a/include/asm-arm/arch-at91/at91_dbgu.h b/include/asm-arm/arch-at91/at91_dbgu.h
index b0369e1..8019ffd 100644
--- a/include/asm-arm/arch-at91/at91_dbgu.h
+++ b/include/asm-arm/arch-at91/at91_dbgu.h
@@ -16,6 +16,7 @@
 #ifndef AT91_DBGU_H
 #define AT91_DBGU_H
 
+#ifdef AT91_DBGU
 #define AT91_DBGU_CR		(AT91_DBGU + 0x00)	/* Control Register */
 #define AT91_DBGU_MR		(AT91_DBGU + 0x04)	/* Mode Register */
 #define AT91_DBGU_IER		(AT91_DBGU + 0x08)	/* Interrupt Enable Register */
@@ -30,6 +31,15 @@
 
 #define AT91_DBGU_CIDR		(AT91_DBGU + 0x40)	/* Chip ID Register */
 #define AT91_DBGU_EXID		(AT91_DBGU + 0x44)	/* Chip ID Extension Register */
+#define AT91_DBGU_FNR		(AT91_DBGU + 0x48)	/* Force NTRST Register [SAM9 only] */
+#define		AT91_DBGU_FNTRST	(1 << 0)		/* Force NTRST */
+
+#endif /* AT91_DBGU */
+
+/*
+ * Some AT91 parts that don't have full DEBUG units still support the ID
+ * and extensions register.
+ */
 #define		AT91_CIDR_VERSION	(0x1f << 0)		/* Version of the Device */
 #define		AT91_CIDR_EPROC		(7    << 5)		/* Embedded Processor */
 #define		AT91_CIDR_NVPSIZ	(0xf  << 8)		/* Nonvolatile Program Memory Size */
@@ -53,7 +63,4 @@
 #define		AT91_CIDR_NVPTYP	(7    << 28)		/* Nonvolatile Program Memory Type */
 #define		AT91_CIDR_EXT		(1    << 31)		/* Extension Flag */
 
-#define AT91_DBGU_FNR		(AT91_DBGU + 0x48)	/* Force NTRST Register [SAM9 only] */
-#define		AT91_DBGU_FNTRST	(1 << 0)		/* Force NTRST */
-
 #endif
diff --git a/include/asm-arm/arch-at91/at91x40.h b/include/asm-arm/arch-at91/at91x40.h
new file mode 100644
index 0000000..612203e
--- /dev/null
+++ b/include/asm-arm/arch-at91/at91x40.h
@@ -0,0 +1,55 @@
+/*
+ * include/asm-arm/arch-at91/at91x40.h
+ *
+ * (C) Copyright 2007, Greg Ungerer <gerg@snapgear.com>
+ *
+ * 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.
+ */
+
+#ifndef AT91X40_H
+#define AT91X40_H
+
+/*
+ *	IRQ list.
+ */
+#define AT91_ID_FIQ		0	/* FIQ */
+#define AT91_ID_SYS		1	/* System Peripheral */
+#define AT91X40_ID_USART0	2	/* USART port 0 */
+#define AT91X40_ID_USART1	3	/* USART port 1 */
+#define AT91X40_ID_TC0		4	/* Timer/Counter 0 */
+#define AT91X40_ID_TC1		5	/* Timer/Counter 1*/
+#define AT91X40_ID_TC2		6	/* Timer/Counter 2*/
+#define AT91X40_ID_WD		7	/* Watchdog? */
+#define AT91X40_ID_PIOA		8	/* Parallel IO Controller A */
+
+#define AT91X40_ID_IRQ0		16	/* External IRQ 0 */
+#define AT91X40_ID_IRQ1		17	/* External IRQ 1 */
+#define AT91X40_ID_IRQ2		18	/* External IRQ 2 */
+
+/*
+ * System Peripherals (offset from AT91_BASE_SYS)
+ */
+#define AT91_BASE_SYS	0xffc00000
+
+#define AT91_EBI	(0xffe00000 - AT91_BASE_SYS)	/* External Bus Interface */
+#define AT91_SF		(0xfff00000 - AT91_BASE_SYS)	/* Special Function */
+#define AT91_USART1	(0xfffcc000 - AT91_BASE_SYS)	/* USART 1 */
+#define AT91_USART0	(0xfffd0000 - AT91_BASE_SYS)	/* USART 0 */
+#define AT91_TC		(0xfffe0000 - AT91_BASE_SYS)	/* Timer Counter */
+#define AT91_PIOA	(0xffff0000 - AT91_BASE_SYS)	/* PIO Controller A */
+#define AT91_PS		(0xffff4000 - AT91_BASE_SYS)	/* Power Save */
+#define AT91_WD		(0xffff8000 - AT91_BASE_SYS)	/* Watchdog Timer */
+#define AT91_AIC	(0xfffff000 - AT91_BASE_SYS)	/* Advanced Interrupt Controller */
+
+/*
+ * The AT91x40 series doesn't have a debug unit like the other AT91 parts.
+ * But it does have a chip identify register and extension ID, so define at
+ * least these here.
+ */
+#define AT91_DBGU_CIDR	(AT91_SF + 0)	/* CIDR in PS segment */
+#define AT91_DBGU_EXID	(AT91_SF + 4)	/* EXID in PS segment */
+
+#endif /* AT91X40_H */
diff --git a/include/asm-arm/arch-at91/cpu.h b/include/asm-arm/arch-at91/cpu.h
index ef93c30..080cbb4 100644
--- a/include/asm-arm/arch-at91/cpu.h
+++ b/include/asm-arm/arch-at91/cpu.h
@@ -28,6 +28,11 @@
 
 #define ARCH_ID_AT91SAM9RL64	0x019b03a0
 
+#define ARCH_ID_AT91M40800	0x14080044
+#define ARCH_ID_AT91R40807	0x44080746
+#define ARCH_ID_AT91M40807	0x14080745
+#define ARCH_ID_AT91R40008	0x44000840
+
 static inline unsigned long at91_cpu_identify(void)
 {
 	return (at91_sys_read(AT91_DBGU_CIDR) & ~AT91_CIDR_VERSION);
diff --git a/include/asm-arm/arch-at91/hardware.h b/include/asm-arm/arch-at91/hardware.h
index 46835e9..8f1cdd3 100644
--- a/include/asm-arm/arch-at91/hardware.h
+++ b/include/asm-arm/arch-at91/hardware.h
@@ -26,18 +26,29 @@
 #include <asm/arch/at91sam9263.h>
 #elif defined(CONFIG_ARCH_AT91SAM9RL)
 #include <asm/arch/at91sam9rl.h>
+#elif defined(CONFIG_ARCH_AT91X40)
+#include <asm/arch/at91x40.h>
 #else
 #error "Unsupported AT91 processor"
 #endif
 
 
+#ifdef CONFIG_MMU
 /*
  * Remap the peripherals from address 0xFFF78000 .. 0xFFFFFFFF
  * to 0xFEF78000 .. 0xFF000000.  (544Kb)
  */
 #define AT91_IO_PHYS_BASE	0xFFF78000
-#define AT91_IO_SIZE		(0xFFFFFFFF - AT91_IO_PHYS_BASE + 1)
 #define AT91_IO_VIRT_BASE	(0xFF000000 - AT91_IO_SIZE)
+#else
+/*
+ * Identity mapping for the non MMU case.
+ */
+#define AT91_IO_PHYS_BASE	AT91_BASE_SYS
+#define AT91_IO_VIRT_BASE	AT91_IO_PHYS_BASE
+#endif
+
+#define AT91_IO_SIZE		(0xFFFFFFFF - AT91_IO_PHYS_BASE + 1)
 
  /* Convert a physical IO address to virtual IO address */
 #define AT91_IO_P2V(x)		((x) - AT91_IO_PHYS_BASE + AT91_IO_VIRT_BASE)
@@ -66,7 +77,11 @@
 #define AT91_CHIPSELECT_7	0x80000000
 
 /* SDRAM */
+#ifdef CONFIG_DRAM_BASE
+#define AT91_SDRAM_BASE		CONFIG_DRAM_BASE
+#else
 #define AT91_SDRAM_BASE		AT91_CHIPSELECT_1
+#endif
 
 /* Clocks */
 #define AT91_SLOW_CLOCK		32768		/* slow clock */
diff --git a/include/asm-arm/arch-at91/timex.h b/include/asm-arm/arch-at91/timex.h
index 2df1ee1..a310698 100644
--- a/include/asm-arm/arch-at91/timex.h
+++ b/include/asm-arm/arch-at91/timex.h
@@ -42,6 +42,11 @@
 #define AT91SAM9_MASTER_CLOCK	100000000
 #define CLOCK_TICK_RATE		(AT91SAM9_MASTER_CLOCK/16)
 
+#elif defined(CONFIG_ARCH_AT91X40)
+
+#define AT91X40_MASTER_CLOCK	40000000
+#define CLOCK_TICK_RATE		(AT91X40_MASTER_CLOCK)
+
 #endif
 
 #endif
diff --git a/include/asm-arm/arch-at91/uncompress.h b/include/asm-arm/arch-at91/uncompress.h
index 30ac587..272a7e0 100644
--- a/include/asm-arm/arch-at91/uncompress.h
+++ b/include/asm-arm/arch-at91/uncompress.h
@@ -33,20 +33,24 @@
  */
 static void putc(int c)
 {
+#ifdef AT91_DBGU
 	void __iomem *sys = (void __iomem *) AT91_BASE_SYS;	/* physical address */
 
 	while (!(__raw_readl(sys + AT91_DBGU_SR) & AT91_DBGU_TXRDY))
 		barrier();
 	__raw_writel(c, sys + AT91_DBGU_THR);
+#endif
 }
 
 static inline void flush(void)
 {
+#ifdef AT91_DBGU
 	void __iomem *sys = (void __iomem *) AT91_BASE_SYS;	/* physical address */
 
 	/* wait for transmission to complete */
 	while (!(__raw_readl(sys + AT91_DBGU_SR) & AT91_DBGU_TXEMPTY))
 		barrier();
+#endif
 }
 
 #define arch_decomp_setup()
diff --git a/include/asm-arm/arch-davinci/clock.h b/include/asm-arm/arch-davinci/clock.h
new file mode 100644
index 0000000..cc168b7
--- /dev/null
+++ b/include/asm-arm/arch-davinci/clock.h
@@ -0,0 +1,22 @@
+/*
+ * include/asm-arm/arch-davinci/clock.h
+ *
+ * Clock control driver for DaVinci - header file
+ *
+ * Authors: Vladimir Barinov <source@mvista.com>
+ *
+ * 2007 (c) MontaVista Software, Inc. 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.
+ */
+#ifndef __ASM_ARCH_DAVINCI_CLOCK_H
+#define __ASM_ARCH_DAVINCI_CLOCK_H
+
+struct clk;
+
+extern int clk_register(struct clk *clk);
+extern void clk_unregister(struct clk *clk);
+extern int davinci_clk_init(void);
+
+#endif
diff --git a/include/asm-arm/arch-davinci/gpio.h b/include/asm-arm/arch-davinci/gpio.h
new file mode 100644
index 0000000..ea24a0e
--- /dev/null
+++ b/include/asm-arm/arch-davinci/gpio.h
@@ -0,0 +1,156 @@
+/*
+ * TI DaVinci GPIO Support
+ *
+ * Copyright (c) 2006 David Brownell
+ * Copyright (c) 2007, MontaVista Software, Inc. <source@mvista.com>
+ *
+ * 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.
+ */
+
+#ifndef	__DAVINCI_GPIO_H
+#define	__DAVINCI_GPIO_H
+
+/*
+ * basic gpio routines
+ *
+ * board-specific init should be done by arch/.../.../board-XXX.c (maybe
+ * initializing banks together) rather than boot loaders; kexec() won't
+ * go through boot loaders.
+ *
+ * the gpio clock will be turned on when gpios are used, and you may also
+ * need to pay attention to PINMUX0 and PINMUX1 to be sure those pins are
+ * used as gpios, not with other peripherals.
+ *
+ * GPIOs are numbered 0..(DAVINCI_N_GPIO-1).  For documentation, and maybe
+ * for later updates, code should write GPIO(N) or:
+ *  - GPIOV18(N) for 1.8V pins, N in 0..53; same as GPIO(0)..GPIO(53)
+ *  - GPIOV33(N) for 3.3V pins, N in 0..17; same as GPIO(54)..GPIO(70)
+ *
+ * For GPIO IRQs use gpio_to_irq(GPIO(N)) or gpio_to_irq(GPIOV33(N)) etc
+ * for now, that's != GPIO(N)
+ */
+#define	GPIO(X)		(X)		/* 0 <= X <= 70 */
+#define	GPIOV18(X)	(X)		/* 1.8V i/o; 0 <= X <= 53 */
+#define	GPIOV33(X)	((X)+54)	/* 3.3V i/o; 0 <= X <= 17 */
+
+struct gpio_controller {
+	u32	dir;
+	u32	out_data;
+	u32	set_data;
+	u32	clr_data;
+	u32	in_data;
+	u32	set_rising;
+	u32	clr_rising;
+	u32	set_falling;
+	u32	clr_falling;
+	u32	intstat;
+};
+
+/* The __gpio_to_controller() and __gpio_mask() functions inline to constants
+ * with constant parameters; or in outlined code they execute at runtime.
+ *
+ * You'd access the controller directly when reading or writing more than
+ * one gpio value at a time, and to support wired logic where the value
+ * being driven by the cpu need not match the value read back.
+ *
+ * These are NOT part of the cross-platform GPIO interface
+ */
+static inline struct gpio_controller *__iomem
+__gpio_to_controller(unsigned gpio)
+{
+	void *__iomem ptr;
+
+	if (gpio < 32)
+		ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x10);
+	else if (gpio < 64)
+		ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x38);
+	else if (gpio < DAVINCI_N_GPIO)
+		ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x60);
+	else
+		ptr = NULL;
+	return ptr;
+}
+
+static inline u32 __gpio_mask(unsigned gpio)
+{
+	return 1 << (gpio % 32);
+}
+
+/* The get/set/clear functions will inline when called with constant
+ * parameters, for low-overhead bitbanging.  Illegal constant parameters
+ * cause link-time errors.
+ *
+ * Otherwise, calls with variable parameters use outlined functions.
+ */
+extern int __error_inval_gpio(void);
+
+extern void __gpio_set(unsigned gpio, int value);
+extern int __gpio_get(unsigned gpio);
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+	if (__builtin_constant_p(value)) {
+		struct gpio_controller	*__iomem g;
+		u32			mask;
+
+		if (gpio >= DAVINCI_N_GPIO)
+			__error_inval_gpio();
+
+		g = __gpio_to_controller(gpio);
+		mask = __gpio_mask(gpio);
+		if (value)
+			__raw_writel(mask, &g->set_data);
+		else
+			__raw_writel(mask, &g->clr_data);
+		return;
+	}
+
+	__gpio_set(gpio, value);
+}
+
+/* Returns zero or nonzero; works for gpios configured as inputs OR
+ * as outputs.
+ *
+ * NOTE: changes in reported values are synchronized to the GPIO clock.
+ * This is most easily seen after calling gpio_set_value() and then immediatly
+ * gpio_get_value(), where the gpio_get_value() would return the old value
+ * until the GPIO clock ticks and the new value gets latched.
+ */
+
+static inline int gpio_get_value(unsigned gpio)
+{
+	struct gpio_controller *__iomem g;
+
+	if (!__builtin_constant_p(gpio))
+		return __gpio_get(gpio);
+
+	if (gpio >= DAVINCI_N_GPIO)
+		return __error_inval_gpio();
+
+	g = __gpio_to_controller(gpio);
+	return !!(__gpio_mask(gpio) & __raw_readl(&g->in_data));
+}
+
+/* powerup default direction is IN */
+extern int gpio_direction_input(unsigned gpio);
+extern int gpio_direction_output(unsigned gpio, int value);
+
+#include <asm-generic/gpio.h>	/* cansleep wrappers */
+
+extern int gpio_request(unsigned gpio, const char *tag);
+extern void gpio_free(unsigned gpio);
+
+static inline int gpio_to_irq(unsigned gpio)
+{
+	return DAVINCI_N_AINTC_IRQ + gpio;
+}
+
+static inline int irq_to_gpio(unsigned irq)
+{
+	return irq - DAVINCI_N_AINTC_IRQ;
+}
+
+#endif				/* __DAVINCI_GPIO_H */
diff --git a/include/asm-arm/arch-davinci/hardware.h b/include/asm-arm/arch-davinci/hardware.h
index 60362d8..a2e8969 100644
--- a/include/asm-arm/arch-davinci/hardware.h
+++ b/include/asm-arm/arch-davinci/hardware.h
@@ -11,4 +11,42 @@
 #ifndef __ASM_ARCH_HARDWARE_H
 #define __ASM_ARCH_HARDWARE_H
 
+/*
+ * Base register addresses
+ */
+#define DAVINCI_DMA_3PCC_BASE			(0x01C00000)
+#define DAVINCI_DMA_3PTC0_BASE			(0x01C10000)
+#define DAVINCI_DMA_3PTC1_BASE			(0x01C10400)
+#define DAVINCI_I2C_BASE			(0x01C21000)
+#define DAVINCI_PWM0_BASE			(0x01C22000)
+#define DAVINCI_PWM1_BASE			(0x01C22400)
+#define DAVINCI_PWM2_BASE			(0x01C22800)
+#define DAVINCI_SYSTEM_MODULE_BASE		(0x01C40000)
+#define DAVINCI_PLL_CNTRL0_BASE			(0x01C40800)
+#define DAVINCI_PLL_CNTRL1_BASE			(0x01C40C00)
+#define DAVINCI_PWR_SLEEP_CNTRL_BASE		(0x01C41000)
+#define DAVINCI_SYSTEM_DFT_BASE			(0x01C42000)
+#define DAVINCI_IEEE1394_BASE			(0x01C60000)
+#define DAVINCI_USB_OTG_BASE			(0x01C64000)
+#define DAVINCI_CFC_ATA_BASE			(0x01C66000)
+#define DAVINCI_SPI_BASE			(0x01C66800)
+#define DAVINCI_GPIO_BASE			(0x01C67000)
+#define DAVINCI_UHPI_BASE			(0x01C67800)
+#define DAVINCI_VPSS_REGS_BASE			(0x01C70000)
+#define DAVINCI_EMAC_CNTRL_REGS_BASE		(0x01C80000)
+#define DAVINCI_EMAC_WRAPPER_CNTRL_REGS_BASE	(0x01C81000)
+#define DAVINCI_EMAC_WRAPPER_RAM_BASE		(0x01C82000)
+#define DAVINCI_MDIO_CNTRL_REGS_BASE		(0x01C84000)
+#define DAVINCI_IMCOP_BASE			(0x01CC0000)
+#define DAVINCI_ASYNC_EMIF_CNTRL_BASE		(0x01E00000)
+#define DAVINCI_VLYNQ_BASE			(0x01E01000)
+#define DAVINCI_MCBSP_BASE			(0x01E02000)
+#define DAVINCI_MMC_SD_BASE			(0x01E10000)
+#define DAVINCI_MS_BASE				(0x01E20000)
+#define DAVINCI_ASYNC_EMIF_DATA_CE0_BASE	(0x02000000)
+#define DAVINCI_ASYNC_EMIF_DATA_CE1_BASE	(0x04000000)
+#define DAVINCI_ASYNC_EMIF_DATA_CE2_BASE	(0x06000000)
+#define DAVINCI_ASYNC_EMIF_DATA_CE3_BASE	(0x08000000)
+#define DAVINCI_VLYNQ_REMOTE_BASE		(0x0C000000)
+
 #endif /* __ASM_ARCH_HARDWARE_H */
diff --git a/include/asm-arm/arch-davinci/mux.h b/include/asm-arm/arch-davinci/mux.h
new file mode 100644
index 0000000..c24b678
--- /dev/null
+++ b/include/asm-arm/arch-davinci/mux.h
@@ -0,0 +1,55 @@
+/*
+ * DaVinci pin multiplexing defines
+ *
+ * Author: Vladimir Barinov, MontaVista Software, Inc. <source@mvista.com>
+ *
+ * 2007 (c) MontaVista Software, Inc. 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.
+ */
+#ifndef __ASM_ARCH_MUX_H
+#define __ASM_ARCH_MUX_H
+
+#define DAVINCI_MUX_AEAW0	0
+#define DAVINCI_MUX_AEAW1	1
+#define DAVINCI_MUX_AEAW2	2
+#define DAVINCI_MUX_AEAW3	3
+#define DAVINCI_MUX_AEAW4	4
+#define DAVINCI_MUX_AECS4	10
+#define DAVINCI_MUX_AECS5	11
+#define DAVINCI_MUX_VLYNQWD0	12
+#define DAVINCI_MUX_VLYNQWD1	13
+#define DAVINCI_MUX_VLSCREN	14
+#define DAVINCI_MUX_VLYNQEN	15
+#define DAVINCI_MUX_HDIREN	16
+#define DAVINCI_MUX_ATAEN	17
+#define DAVINCI_MUX_RGB666	22
+#define DAVINCI_MUX_RGB888	23
+#define DAVINCI_MUX_LOEEN	24
+#define DAVINCI_MUX_LFLDEN	25
+#define DAVINCI_MUX_CWEN	26
+#define DAVINCI_MUX_CFLDEN	27
+#define DAVINCI_MUX_HPIEN	29
+#define DAVINCI_MUX_1394EN	30
+#define DAVINCI_MUX_EMACEN	31
+
+#define DAVINCI_MUX_LEVEL2	32
+#define DAVINCI_MUX_UART0	(DAVINCI_MUX_LEVEL2 + 0)
+#define DAVINCI_MUX_UART1	(DAVINCI_MUX_LEVEL2 + 1)
+#define DAVINCI_MUX_UART2	(DAVINCI_MUX_LEVEL2 + 2)
+#define DAVINCI_MUX_U2FLO	(DAVINCI_MUX_LEVEL2 + 3)
+#define DAVINCI_MUX_PWM0	(DAVINCI_MUX_LEVEL2 + 4)
+#define DAVINCI_MUX_PWM1	(DAVINCI_MUX_LEVEL2 + 5)
+#define DAVINCI_MUX_PWM2	(DAVINCI_MUX_LEVEL2 + 6)
+#define DAVINCI_MUX_I2C		(DAVINCI_MUX_LEVEL2 + 7)
+#define DAVINCI_MUX_SPI		(DAVINCI_MUX_LEVEL2 + 8)
+#define DAVINCI_MUX_MSTK	(DAVINCI_MUX_LEVEL2 + 9)
+#define DAVINCI_MUX_ASP		(DAVINCI_MUX_LEVEL2 + 10)
+#define DAVINCI_MUX_CLK0	(DAVINCI_MUX_LEVEL2 + 16)
+#define DAVINCI_MUX_CLK1	(DAVINCI_MUX_LEVEL2 + 17)
+#define DAVINCI_MUX_TIMIN	(DAVINCI_MUX_LEVEL2 + 18)
+
+extern void davinci_mux_peripheral(unsigned int mux, unsigned int enable);
+
+#endif /* __ASM_ARCH_MUX_H */
diff --git a/include/asm-arm/arch-imx/gpio.h b/include/asm-arm/arch-imx/gpio.h
new file mode 100644
index 0000000..4860232
--- /dev/null
+++ b/include/asm-arm/arch-imx/gpio.h
@@ -0,0 +1,102 @@
+#ifndef _IMX_GPIO_H
+
+#include <asm/arch/imx-regs.h>
+
+#define IMX_GPIO_ALLOC_MODE_NORMAL	0
+#define IMX_GPIO_ALLOC_MODE_NO_ALLOC	1
+#define IMX_GPIO_ALLOC_MODE_TRY_ALLOC	2
+#define IMX_GPIO_ALLOC_MODE_ALLOC_ONLY	4
+#define IMX_GPIO_ALLOC_MODE_RELEASE	8
+
+extern int imx_gpio_request(unsigned gpio, const char *label);
+
+extern void imx_gpio_free(unsigned gpio);
+
+extern int imx_gpio_setup_multiple_pins(const int *pin_list, unsigned count,
+					int alloc_mode, const char *label);
+
+extern int imx_gpio_direction_input(unsigned gpio);
+
+extern int imx_gpio_direction_output(unsigned gpio, int value);
+
+extern void __imx_gpio_set_value(unsigned gpio, int value);
+
+static inline int imx_gpio_get_value(unsigned gpio)
+{
+	return SSR(gpio >> GPIO_PORT_SHIFT) & (1 << (gpio & GPIO_PIN_MASK));
+}
+
+static inline void imx_gpio_set_value_inline(unsigned gpio, int value)
+{
+	unsigned long flags;
+
+	raw_local_irq_save(flags);
+	if(value)
+		DR(gpio >> GPIO_PORT_SHIFT) |= (1 << (gpio & GPIO_PIN_MASK));
+	else
+		DR(gpio >> GPIO_PORT_SHIFT) &= ~(1 << (gpio & GPIO_PIN_MASK));
+	raw_local_irq_restore(flags);
+}
+
+static inline void imx_gpio_set_value(unsigned gpio, int value)
+{
+	if(__builtin_constant_p(gpio))
+		imx_gpio_set_value_inline(gpio, value);
+	else
+		__imx_gpio_set_value(gpio, value);
+}
+
+extern int imx_gpio_to_irq(unsigned gpio);
+
+extern int imx_irq_to_gpio(unsigned irq);
+
+/*-------------------------------------------------------------------------*/
+
+/* Wrappers for "new style" GPIO calls. These calls i.MX specific versions
+ * to allow future extension of GPIO logic.
+ */
+
+static inline int gpio_request(unsigned gpio, const char *label)
+{
+	return imx_gpio_request(gpio, label);
+}
+
+static inline void gpio_free(unsigned gpio)
+{
+	imx_gpio_free(gpio);
+}
+
+static inline  int gpio_direction_input(unsigned gpio)
+{
+	return imx_gpio_direction_input(gpio);
+}
+
+static inline int gpio_direction_output(unsigned gpio, int value)
+{
+	return imx_gpio_direction_output(gpio, value);
+}
+
+static inline int gpio_get_value(unsigned gpio)
+{
+	return imx_gpio_get_value(gpio);
+}
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+	imx_gpio_set_value(gpio, value);
+}
+
+#include <asm-generic/gpio.h>		/* cansleep wrappers */
+
+static inline int gpio_to_irq(unsigned gpio)
+{
+	return imx_gpio_to_irq(gpio);
+}
+
+static inline int irq_to_gpio(unsigned irq)
+{
+	return imx_irq_to_gpio(irq);
+}
+
+
+#endif
diff --git a/include/asm-arm/arch-imx/imx-regs.h b/include/asm-arm/arch-imx/imx-regs.h
index 30de404..fb9de27 100644
--- a/include/asm-arm/arch-imx/imx-regs.h
+++ b/include/asm-arm/arch-imx/imx-regs.h
@@ -77,6 +77,8 @@
 #define SWR(x)     __REG2(IMX_GPIO_BASE + 0x3c, ((x) & 3) << 8)
 #define PUEN(x)    __REG2(IMX_GPIO_BASE + 0x40, ((x) & 3) << 8)
 
+#define GPIO_PORT_MAX  3
+
 #define GPIO_PIN_MASK 0x1f
 #define GPIO_PORT_MASK (0x3 << 5)
 
diff --git a/include/asm-arm/arch-ixp4xx/ixdp425.h b/include/asm-arm/arch-ixp4xx/ixdp425.h
index 3d3820d..e0791af 100644
--- a/include/asm-arm/arch-ixp4xx/ixdp425.h
+++ b/include/asm-arm/arch-ixp4xx/ixdp425.h
@@ -32,4 +32,8 @@
 #define	IXDP425_PCI_INTC_PIN	9
 #define	IXDP425_PCI_INTD_PIN	8
 
+/* NAND Flash pins */
+#define	IXDP425_NAND_NCE_PIN	12
 
+#define	IXDP425_NAND_CMD_BYTE	0x01
+#define	IXDP425_NAND_ADDR_BYTE	0x02
diff --git a/include/asm-arm/arch-ixp4xx/uncompress.h b/include/asm-arm/arch-ixp4xx/uncompress.h
index 09ae6c9..f7a35b7 100644
--- a/include/asm-arm/arch-ixp4xx/uncompress.h
+++ b/include/asm-arm/arch-ixp4xx/uncompress.h
@@ -38,9 +38,10 @@
 static __inline__ void __arch_decomp_setup(unsigned long arch_id)
 {
 	/*
-	 * Coyote and gtwx5715 only have UART2 connected
+	 * Some boards are using UART2 as console
 	 */
-	if (machine_is_adi_coyote() || machine_is_gtwx5715())
+	if (machine_is_adi_coyote() || machine_is_gtwx5715() ||
+			 machine_is_gateway7001() || machine_is_wg302v2())
 		uart_base = (volatile u32*) IXP4XX_UART2_BASE_PHYS;
 	else
 		uart_base = (volatile u32*) IXP4XX_UART1_BASE_PHYS;
diff --git a/include/asm-arm/arch-pxa/dma.h b/include/asm-arm/arch-pxa/dma.h
index bed042d..3280ee2 100644
--- a/include/asm-arm/arch-pxa/dma.h
+++ b/include/asm-arm/arch-pxa/dma.h
@@ -30,30 +30,12 @@
 	DMA_PRIO_LOW = 2
 } pxa_dma_prio;
 
-#if defined(CONFIG_PXA27x)
-
-#define PXA_DMA_CHANNELS	32
-
-#define pxa_for_each_dma_prio(ch, prio)					\
-for (									\
-	ch = prio * 4;							\
-	ch != (4 << prio) + 16;						\
-	ch = (ch + 1 == (4 << prio)) ? (prio * 4 + 16) : (ch + 1)	\
-)
-
-#elif defined(CONFIG_PXA25x)
-
-#define PXA_DMA_CHANNELS	16
-
-#define pxa_for_each_dma_prio(ch, prio)					\
-	for (ch = prio * 4; ch != (4 << prio); ch++)
-
-#endif
-
 /*
  * DMA registration
  */
 
+int __init pxa_init_dma(int num_ch);
+
 int pxa_request_dma (char *name,
 			 pxa_dma_prio prio,
 			 void (*irq_handler)(int, void *),
diff --git a/include/asm-arm/arch-pxa/entry-macro.S b/include/asm-arm/arch-pxa/entry-macro.S
index 1d5fbb9..b7e7308 100644
--- a/include/asm-arm/arch-pxa/entry-macro.S
+++ b/include/asm-arm/arch-pxa/entry-macro.S
@@ -20,20 +20,38 @@
 		.endm
 
 		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
-#ifdef CONFIG_PXA27x
-		mrc	p6, 0, \irqstat, c0, c0, 0		@ ICIP
-		mrc	p6, 0, \irqnr, c1, c0, 0		@ ICMR
-#else
+		mrc	p15, 0, \tmp, c0, c0, 0		@ CPUID
+		mov	\tmp, \tmp, lsr #13
+		and	\tmp, \tmp, #0x7		@ Core G
+		cmp	\tmp, #1
+		bhi	1004f
+
 		mov	\base, #io_p2v(0x40000000)	@ IIR Ctl = 0x40d00000
 		add	\base, \base, #0x00d00000
 		ldr	\irqstat, [\base, #0]		@ ICIP
 		ldr	\irqnr, [\base, #4]		@ ICMR
-#endif
+		b	1002f
+
+1004:
+		mrc	p6, 0, \irqstat, c6, c0, 0	@ ICIP2
+		mrc	p6, 0, \irqnr, c7, c0, 0	@ ICMR2
+		ands	\irqstat, \irqstat, \irqnr
+		beq	1003f
+		rsb	\irqstat, \irqnr, #0
+		and	\irqstat, \irqstat, \irqnr
+		clz	\irqnr, \irqstat
+		rsb	\irqnr, \irqnr, #31
+		add	\irqnr, \irqnr, #32
+		b	1001f
+1003:
+		mrc	p6, 0, \irqstat, c0, c0, 0	@ ICIP
+		mrc	p6, 0, \irqnr, c1, c0, 0	@ ICMR
+1002:
 		ands	\irqnr, \irqstat, \irqnr
 		beq	1001f
 		rsb	\irqstat, \irqnr, #0
 		and	\irqstat, \irqstat, \irqnr
 		clz	\irqnr, \irqstat
-		rsb	\irqnr, \irqnr, #(31 - PXA_IRQ_SKIP)
+		rsb	\irqnr, \irqnr, #31
 1001:
 		.endm
diff --git a/include/asm-arm/arch-pxa/hardware.h b/include/asm-arm/arch-pxa/hardware.h
index e2bdc2f..3861217 100644
--- a/include/asm-arm/arch-pxa/hardware.h
+++ b/include/asm-arm/arch-pxa/hardware.h
@@ -62,6 +62,42 @@
 
 #ifndef __ASSEMBLY__
 
+#define __cpu_is_pxa21x(id)				\
+	({						\
+		unsigned int _id = (id) >> 4 & 0xf3f;	\
+		_id == 0x212;				\
+	})
+
+#define __cpu_is_pxa25x(id)				\
+	({						\
+		unsigned int _id = (id) >> 4 & 0xfff;	\
+		_id == 0x2d0 || _id == 0x290;		\
+	})
+
+#define __cpu_is_pxa27x(id)				\
+	({						\
+		unsigned int _id = (id) >> 4 & 0xfff;	\
+		_id == 0x411;				\
+	})
+
+#define cpu_is_pxa21x()					\
+	({						\
+		unsigned int id = read_cpuid(CPUID_ID);	\
+		__cpu_is_pxa21x(id);			\
+	})
+
+#define cpu_is_pxa25x()					\
+	({						\
+		unsigned int id = read_cpuid(CPUID_ID);	\
+		__cpu_is_pxa25x(id);			\
+	})
+
+#define cpu_is_pxa27x()					\
+	({						\
+		unsigned int id = read_cpuid(CPUID_ID);	\
+		__cpu_is_pxa27x(id);			\
+	})
+
 /*
  * Handy routine to set GPIO alternate functions
  */
diff --git a/include/asm-arm/arch-pxa/irqs.h b/include/asm-arm/arch-pxa/irqs.h
index 67ed436..a07fe0f 100644
--- a/include/asm-arm/arch-pxa/irqs.h
+++ b/include/asm-arm/arch-pxa/irqs.h
@@ -11,14 +11,9 @@
  */
 
 
+#define PXA_IRQ(x)	(x)
+
 #ifdef CONFIG_PXA27x
-#define PXA_IRQ_SKIP	0
-#else
-#define PXA_IRQ_SKIP	7
-#endif
-
-#define PXA_IRQ(x)	((x) - PXA_IRQ_SKIP)
-
 #define IRQ_SSP3	PXA_IRQ(0)	/* SSP3 service request */
 #define IRQ_MSL		PXA_IRQ(1)	/* MSL Interface interrupt */
 #define IRQ_USBH2	PXA_IRQ(2)	/* USB Host interrupt 1 (OHCI) */
@@ -26,6 +21,8 @@
 #define IRQ_KEYPAD	PXA_IRQ(4)	/* Key pad controller */
 #define IRQ_MEMSTK	PXA_IRQ(5)	/* Memory Stick interrupt */
 #define IRQ_PWRI2C	PXA_IRQ(6)	/* Power I2C interrupt */
+#endif
+
 #define IRQ_HWUART	PXA_IRQ(7)	/* HWUART Transmit/Receive/Error (PXA26x) */
 #define IRQ_OST_4_11	PXA_IRQ(7)	/* OS timer 4-11 matches (PXA27x) */
 #define	IRQ_GPIO0	PXA_IRQ(8)	/* GPIO0 Edge Detect */
@@ -58,18 +55,15 @@
 #ifdef CONFIG_PXA27x
 #define IRQ_TPM		PXA_IRQ(32)	/* TPM interrupt */
 #define IRQ_CAMERA	PXA_IRQ(33)	/* Camera Interface */
-
-#define PXA_INTERNAL_IRQS 34
-#else
-#define PXA_INTERNAL_IRQS 32
 #endif
 
-#define GPIO_2_x_TO_IRQ(x)	\
-			PXA_IRQ((x) - 2 + PXA_INTERNAL_IRQS)
+#define PXA_GPIO_IRQ_BASE	(64)
+#define PXA_GPIO_IRQ_NUM	(128)
+
+#define GPIO_2_x_TO_IRQ(x)	(PXA_GPIO_IRQ_BASE + (x))
 #define IRQ_GPIO(x)	(((x) < 2) ? (IRQ_GPIO0 + (x)) : GPIO_2_x_TO_IRQ(x))
 
-#define IRQ_TO_GPIO_2_x(i)	\
-			((i) - IRQ_GPIO(2) + 2)
+#define IRQ_TO_GPIO_2_x(i)	((i) - PXA_GPIO_IRQ_BASE)
 #define IRQ_TO_GPIO(i)	(((i) < IRQ_GPIO(2)) ? ((i) - IRQ_GPIO0) : IRQ_TO_GPIO_2_x(i))
 
 #if defined(CONFIG_PXA25x)
@@ -84,7 +78,7 @@
  * these.  If you need more, increase IRQ_BOARD_END, but keep it
  * within sensible limits.
  */
-#define IRQ_BOARD_START		(IRQ_GPIO(PXA_LAST_GPIO) + 1)
+#define IRQ_BOARD_START		(PXA_GPIO_IRQ_BASE + PXA_GPIO_IRQ_NUM)
 #define IRQ_BOARD_END		(IRQ_BOARD_START + 16)
 
 #define IRQ_SA1111_START	(IRQ_BOARD_END)
diff --git a/include/asm-arm/arch-pxa/pm.h b/include/asm-arm/arch-pxa/pm.h
index 7a8a1cd..52243a6 100644
--- a/include/asm-arm/arch-pxa/pm.h
+++ b/include/asm-arm/arch-pxa/pm.h
@@ -9,4 +9,3 @@
 
 extern int pxa_pm_prepare(suspend_state_t state);
 extern int pxa_pm_enter(suspend_state_t state);
-extern int pxa_pm_finish(suspend_state_t state);
diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h
index dbcc929..e68b593 100644
--- a/include/asm-arm/arch-pxa/pxa-regs.h
+++ b/include/asm-arm/arch-pxa/pxa-regs.h
@@ -1765,29 +1765,9 @@
 #define SSACD_P(x) (*(((x) == 1) ? &SSACD_P1 : ((x) == 2) ? &SSACD_P2 : ((x) == 3) ? &SSACD_P3 : NULL))
 
 /*
- * MultiMediaCard (MMC) controller
+ * MultiMediaCard (MMC) controller - see drivers/mmc/host/pxamci.h
  */
 
-#define MMC_STRPCL	__REG(0x41100000)  /* Control to start and stop MMC clock */
-#define MMC_STAT	__REG(0x41100004)  /* MMC Status Register (read only) */
-#define MMC_CLKRT	__REG(0x41100008)  /* MMC clock rate */
-#define MMC_SPI		__REG(0x4110000c)  /* SPI mode control bits */
-#define MMC_CMDAT	__REG(0x41100010)  /* Command/response/data sequence control */
-#define MMC_RESTO	__REG(0x41100014)  /* Expected response time out */
-#define MMC_RDTO	__REG(0x41100018)  /* Expected data read time out */
-#define MMC_BLKLEN	__REG(0x4110001c)  /* Block length of data transaction */
-#define MMC_NOB		__REG(0x41100020)  /* Number of blocks, for block mode */
-#define MMC_PRTBUF	__REG(0x41100024)  /* Partial MMC_TXFIFO FIFO written */
-#define MMC_I_MASK	__REG(0x41100028)  /* Interrupt Mask */
-#define MMC_I_REG	__REG(0x4110002c)  /* Interrupt Register (read only) */
-#define MMC_CMD		__REG(0x41100030)  /* Index of current command */
-#define MMC_ARGH	__REG(0x41100034)  /* MSW part of the current command argument */
-#define MMC_ARGL	__REG(0x41100038)  /* LSW part of the current command argument */
-#define MMC_RES		__REG(0x4110003c)  /* Response FIFO (read only) */
-#define MMC_RXFIFO	__REG(0x41100040)  /* Receive FIFO (read only) */
-#define MMC_TXFIFO	__REG(0x41100044)  /* Transmit FIFO (write only) */
-
-
 /*
  * Core Clock
  */
diff --git a/include/asm-arm/elf.h b/include/asm-arm/elf.h
index 3679a8a..d7a777f 100644
--- a/include/asm-arm/elf.h
+++ b/include/asm-arm/elf.h
@@ -7,6 +7,7 @@
  */
 #include <asm/ptrace.h>
 #include <asm/user.h>
+#include <asm/hwcap.h>
 
 typedef unsigned long elf_greg_t;
 typedef unsigned long elf_freg_t[3];
@@ -39,31 +40,9 @@
 #endif
 #define ELF_ARCH	EM_ARM
 
-/*
- * HWCAP flags - for elf_hwcap (in kernel) and AT_HWCAP
- */
-#define HWCAP_SWP	1
-#define HWCAP_HALF	2
-#define HWCAP_THUMB	4
-#define HWCAP_26BIT	8	/* Play it safe */
-#define HWCAP_FAST_MULT	16
-#define HWCAP_FPA	32
-#define HWCAP_VFP	64
-#define HWCAP_EDSP	128
-#define HWCAP_JAVA	256
-#define HWCAP_IWMMXT	512
-#define HWCAP_CRUNCH	1024
-
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 /*
- * This yields a mask that user programs can use to figure out what
- * instruction set this cpu supports.
- */
-#define ELF_HWCAP	(elf_hwcap)
-extern unsigned int elf_hwcap;
-
-/*
  * This yields a string that ld.so will use to load implementation
  * specific libraries for optimization.  This is more specific in
  * intent than poking at uname or /proc/cpuinfo.
diff --git a/include/asm-arm/hwcap.h b/include/asm-arm/hwcap.h
new file mode 100644
index 0000000..01a1391
--- /dev/null
+++ b/include/asm-arm/hwcap.h
@@ -0,0 +1,28 @@
+#ifndef __ASMARM_HWCAP_H
+#define __ASMARM_HWCAP_H
+
+/*
+ * HWCAP flags - for elf_hwcap (in kernel) and AT_HWCAP
+ */
+#define HWCAP_SWP	1
+#define HWCAP_HALF	2
+#define HWCAP_THUMB	4
+#define HWCAP_26BIT	8	/* Play it safe */
+#define HWCAP_FAST_MULT	16
+#define HWCAP_FPA	32
+#define HWCAP_VFP	64
+#define HWCAP_EDSP	128
+#define HWCAP_JAVA	256
+#define HWCAP_IWMMXT	512
+#define HWCAP_CRUNCH	1024
+
+#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
+/*
+ * This yields a mask that user programs can use to figure out what
+ * instruction set this cpu supports.
+ */
+#define ELF_HWCAP	(elf_hwcap)
+extern unsigned int elf_hwcap;
+#endif
+
+#endif
diff --git a/include/asm-arm/ptrace.h b/include/asm-arm/ptrace.h
index ee3d93c..7aaa206 100644
--- a/include/asm-arm/ptrace.h
+++ b/include/asm-arm/ptrace.h
@@ -10,6 +10,8 @@
 #ifndef __ASM_ARM_PTRACE_H
 #define __ASM_ARM_PTRACE_H
 
+#include <asm/hwcap.h>
+
 #define PTRACE_GETREGS		12
 #define PTRACE_SETREGS		13
 #define PTRACE_GETFPREGS	14
@@ -45,6 +47,7 @@
 #define PSR_T_BIT	0x00000020
 #define PSR_F_BIT	0x00000040
 #define PSR_I_BIT	0x00000080
+#define PSR_A_BIT	0x00000100
 #define PSR_J_BIT	0x01000000
 #define PSR_Q_BIT	0x08000000
 #define PSR_V_BIT	0x10000000
@@ -103,6 +106,10 @@
 #define thumb_mode(regs) (0)
 #endif
 
+#define isa_mode(regs) \
+	((((regs)->ARM_cpsr & PSR_J_BIT) >> 23) | \
+	 (((regs)->ARM_cpsr & PSR_T_BIT) >> 5))
+
 #define processor_mode(regs) \
 	((regs)->ARM_cpsr & MODE_MASK)
 
@@ -117,14 +124,17 @@
  */
 static inline int valid_user_regs(struct pt_regs *regs)
 {
-	if (user_mode(regs) &&
-	    (regs->ARM_cpsr & (PSR_F_BIT|PSR_I_BIT)) == 0)
+	if (user_mode(regs) && (regs->ARM_cpsr & PSR_I_BIT) == 0) {
+		regs->ARM_cpsr &= ~(PSR_F_BIT | PSR_A_BIT);
 		return 1;
+	}
 
 	/*
 	 * Force CPSR to something logical...
 	 */
-	regs->ARM_cpsr &= PSR_f | PSR_s | PSR_x | PSR_T_BIT | MODE32_BIT;
+	regs->ARM_cpsr &= PSR_f | PSR_s | (PSR_x & ~PSR_A_BIT) | PSR_T_BIT | MODE32_BIT;
+	if (!(elf_hwcap & HWCAP_26BIT))
+		regs->ARM_cpsr |= USR_MODE;
 
 	return 0;
 }